// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/compiler.h"

#include "vm/assembler.h"

#include "vm/ast_printer.h"
#include "vm/code_generator.h"
#include "vm/code_patcher.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/deopt_instructions.h"
#include "vm/disassembler.h"
#include "vm/exceptions.h"
#include "vm/flags.h"
#include "vm/flow_graph.h"
#include "vm/flow_graph_allocator.h"
#include "vm/flow_graph_builder.h"
#include "vm/flow_graph_compiler.h"
#include "vm/flow_graph_inliner.h"
#include "vm/flow_graph_optimizer.h"
#include "vm/flow_graph_type_propagator.h"
#include "vm/il_printer.h"
#include "vm/longjump.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/os.h"
#include "vm/parser.h"
#include "vm/scanner.h"
#include "vm/symbols.h"
#include "vm/timer.h"

namespace dart {

DEFINE_FLAG(bool, disassemble, false, "Disassemble dart code.");
DEFINE_FLAG(bool, disassemble_optimized, false, "Disassemble optimized code.");
DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler.");
DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations.");
DEFINE_FLAG(bool, constant_propagation, true,
    "Do conditional constant propagation/unreachable code elimination.");
DEFINE_FLAG(bool, common_subexpression_elimination, true,
    "Do common subexpression elimination.");
DEFINE_FLAG(bool, loop_invariant_code_motion, true,
    "Do loop invariant code motion.");
DEFINE_FLAG(bool, propagate_types, true, "Do static type propagation.");
DEFINE_FLAG(int, deoptimization_counter_threshold, 16,
    "How many times we allow deoptimization before we disallow optimization.");
DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining");
DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis");
DEFINE_FLAG(bool, verify_compiler, false,
    "Enable compiler verification assertions");
DECLARE_FLAG(bool, print_flow_graph);
DECLARE_FLAG(bool, print_flow_graph_optimized);
DECLARE_FLAG(bool, trace_failed_optimization_attempts);

// Compile a function. Should call only if the function has not been compiled.
//   Arg0: function object.
DEFINE_RUNTIME_ENTRY(CompileFunction, 1) {
  ASSERT(arguments.ArgCount() == kCompileFunctionRuntimeEntry.argument_count());
  const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
  ASSERT(!function.HasCode());
  const Error& error = Error::Handle(Compiler::CompileFunction(function));
  if (!error.IsNull()) {
    Exceptions::PropagateError(error);
  }
}


RawError* Compiler::Compile(const Library& library, const Script& script) {
  Isolate* isolate = Isolate::Current();
  StackZone zone(isolate);
  LongJump* base = isolate->long_jump_base();
  LongJump jump;
  isolate->set_long_jump_base(&jump);
  if (setjmp(*jump.Set()) == 0) {
    if (FLAG_trace_compiler) {
      const String& script_url = String::Handle(script.url());
      // TODO(iposva): Extract script kind.
      OS::Print("Compiling %s '%s'\n", "", script_url.ToCString());
    }
    const String& library_key = String::Handle(library.private_key());
    script.Tokenize(library_key);
    Parser::ParseCompilationUnit(library, script);
    isolate->set_long_jump_base(base);
    return Error::null();
  } else {
    Error& error = Error::Handle();
    error = isolate->object_store()->sticky_error();
    isolate->object_store()->clear_sticky_error();
    isolate->set_long_jump_base(base);
    return error.raw();
  }
  UNREACHABLE();
  return Error::null();
}


static void InstallUnoptimizedCode(const Function& function) {
  // Disable optimized code.
  ASSERT(function.HasOptimizedCode());
  if (FLAG_trace_compiler) {
    OS::Print("--> patching entry %#"Px"\n",
              Code::Handle(function.CurrentCode()).EntryPoint());
  }
  function.SwitchToUnoptimizedCode();
  if (FLAG_trace_compiler) {
    OS::Print("--> restoring entry at %#"Px"\n",
              Code::Handle(function.unoptimized_code()).EntryPoint());
  }
}


// Return false if bailed out.
static bool CompileParsedFunctionHelper(const ParsedFunction& parsed_function,
                                        bool optimized) {
  TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer);
  bool is_compiled = false;
  Isolate* isolate = Isolate::Current();
  HANDLESCOPE(isolate);
  ASSERT(isolate->ic_data_array() == Array::null());  // Must be reset to null.
  const intptr_t prev_deopt_id = isolate->deopt_id();
  isolate->set_deopt_id(0);
  LongJump* old_base = isolate->long_jump_base();
  LongJump bailout_jump;
  isolate->set_long_jump_base(&bailout_jump);
  if (setjmp(*bailout_jump.Set()) == 0) {
    FlowGraph* flow_graph = NULL;
    // TimerScope needs an isolate to be properly terminated in case of a
    // LongJump.
    {
      TimerScope timer(FLAG_compiler_stats,
                       &CompilerStats::graphbuilder_timer,
                       isolate);
      if (optimized) {
        ASSERT(parsed_function.function().HasCode());
        // Extract type feedback before the graph is built, as the graph
        // builder uses it to attach it to nodes.
        // Do not use type feedback to optimize a function that was
        // deoptimized too often.
        if (parsed_function.function().deoptimization_counter() <
            FLAG_deoptimization_counter_threshold) {
          const Code& unoptimized_code =
              Code::Handle(parsed_function.function().unoptimized_code());
          isolate->set_ic_data_array(
              unoptimized_code.ExtractTypeFeedbackArray());
        }
      }

      // Build the flow graph.
      FlowGraphBuilder builder(parsed_function, NULL);  // NULL = not inlining.
      flow_graph = builder.BuildGraph();
    }

    if (optimized) {
      TimerScope timer(FLAG_compiler_stats,
                       &CompilerStats::ssa_timer,
                       isolate);
      // Transform to SSA (virtual register 0 and no inlining arguments).
      flow_graph->ComputeSSA(0, NULL);
      DEBUG_ASSERT(flow_graph->VerifyUseLists());
    }

    if (FLAG_print_flow_graph ||
        (optimized && FLAG_print_flow_graph_optimized)) {
      FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph);
    }

    // Collect all instance fields that are loaded in the graph and
    // have non-generic type feedback attached to them that can
    // potentially affect optimizations.
    GrowableArray<Field*> guarded_fields(10);
    if (optimized) {
      TimerScope timer(FLAG_compiler_stats,
                       &CompilerStats::graphoptimizer_timer,
                       isolate);

      FlowGraphOptimizer optimizer(flow_graph, &guarded_fields);
      optimizer.ApplyICData();
      DEBUG_ASSERT(flow_graph->VerifyUseLists());

      // Optimize (a << b) & c patterns. Must occur before
      // 'SelectRepresentations' which inserts conversion nodes.
      // TODO(srdjan): Moved before inlining until environment use list can
      // be used to detect when shift-left is outside the scope of bit-and.
      optimizer.TryOptimizeLeftShiftWithBitAndPattern();
      DEBUG_ASSERT(flow_graph->VerifyUseLists());

      // Inlining (mutates the flow graph)
      if (FLAG_use_inlining) {
        TimerScope timer(FLAG_compiler_stats,
                         &CompilerStats::graphinliner_timer);
        FlowGraphInliner inliner(flow_graph, &guarded_fields);
        inliner.Inline();
        // Use lists are maintained and validated by the inliner.
        DEBUG_ASSERT(flow_graph->VerifyUseLists());
      }

      // Propagate types and eliminate more type tests.
      if (FLAG_propagate_types) {
        FlowGraphTypePropagator propagator(flow_graph);
        propagator.Propagate();
        DEBUG_ASSERT(flow_graph->VerifyUseLists());
      }

      // Use propagated class-ids to optimize further.
      optimizer.ApplyClassIds();
      DEBUG_ASSERT(flow_graph->VerifyUseLists());

      // Do optimizations that depend on the propagated type information.
      optimizer.Canonicalize();
      DEBUG_ASSERT(flow_graph->VerifyUseLists());

      BranchSimplifier::Simplify(flow_graph);
      DEBUG_ASSERT(flow_graph->VerifyUseLists());

      IfConverter::Simplify(flow_graph);
      DEBUG_ASSERT(flow_graph->VerifyUseLists());

      if (FLAG_constant_propagation) {
        ConstantPropagator::Optimize(flow_graph);
        DEBUG_ASSERT(flow_graph->VerifyUseLists());
        // A canonicalization pass to remove e.g. smi checks on smi constants.
        optimizer.Canonicalize();
        DEBUG_ASSERT(flow_graph->VerifyUseLists());
        // Canonicalization introduced more opportunities for constant
        // propagation.
        ConstantPropagator::Optimize(flow_graph);
        DEBUG_ASSERT(flow_graph->VerifyUseLists());
      }

      // Propagate types and eliminate even more type tests.
      if (FLAG_propagate_types) {
        // Recompute types after constant propagation to infer more precise
        // types for uses that were previously reached by now eliminated phis.
        FlowGraphTypePropagator propagator(flow_graph);
        propagator.Propagate();
        DEBUG_ASSERT(flow_graph->VerifyUseLists());
      }

      // Unbox doubles. Performed after constant propagation to minimize
      // interference from phis merging double values and tagged
      // values comming from dead paths.
      optimizer.SelectRepresentations();
      DEBUG_ASSERT(flow_graph->VerifyUseLists());

      if (FLAG_common_subexpression_elimination ||
          FLAG_loop_invariant_code_motion) {
        flow_graph->ComputeBlockEffects();
      }

      if (FLAG_common_subexpression_elimination) {
        if (DominatorBasedCSE::Optimize(flow_graph)) {
          DEBUG_ASSERT(flow_graph->VerifyUseLists());
          // Do another round of CSE to take secondary effects into account:
          // e.g. when eliminating dependent loads (a.x[0] + a.x[0])
          // TODO(fschneider): Change to a one-pass optimization pass.
          DominatorBasedCSE::Optimize(flow_graph);
          DEBUG_ASSERT(flow_graph->VerifyUseLists());
        }
      }
      if (FLAG_loop_invariant_code_motion &&
          (parsed_function.function().deoptimization_counter() <
           (FLAG_deoptimization_counter_threshold - 1))) {
        LICM licm(flow_graph);
        licm.Optimize();
        DEBUG_ASSERT(flow_graph->VerifyUseLists());
      }

      if (FLAG_range_analysis) {
        // We have to perform range analysis after LICM because it
        // optimistically moves CheckSmi through phis into loop preheaders
        // making some phis smi.
        optimizer.InferSmiRanges();
        DEBUG_ASSERT(flow_graph->VerifyUseLists());
      }

      if (FLAG_constant_propagation) {
        // Constant propagation can use information from range analysis to
        // find unreachable branch targets.
        ConstantPropagator::OptimizeBranches(flow_graph);
        DEBUG_ASSERT(flow_graph->VerifyUseLists());
      }

      // The final canonicalization pass before the code generation.
      if (FLAG_propagate_types) {
        // Recompute types after code movement was done to ensure correct
        // reaching types for hoisted values.
        FlowGraphTypePropagator propagator(flow_graph);
        propagator.Propagate();
        DEBUG_ASSERT(flow_graph->VerifyUseLists());
      }
      optimizer.Canonicalize();
      DEBUG_ASSERT(flow_graph->VerifyUseLists());

      // Perform register allocation on the SSA graph.
      FlowGraphAllocator allocator(*flow_graph);
      allocator.AllocateRegisters();

      if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
        FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph);
      }
    }

    Assembler assembler;
    FlowGraphCompiler graph_compiler(&assembler,
                                     *flow_graph,
                                     optimized);
    {
      TimerScope timer(FLAG_compiler_stats,
                       &CompilerStats::graphcompiler_timer,
                       isolate);
      graph_compiler.CompileGraph();
    }
    {
      TimerScope timer(FLAG_compiler_stats,
                       &CompilerStats::codefinalizer_timer,
                       isolate);
      const Function& function = parsed_function.function();
      const Code& code = Code::Handle(
          Code::FinalizeCode(function, &assembler, optimized));
      code.set_is_optimized(optimized);
      graph_compiler.FinalizePcDescriptors(code);
      graph_compiler.FinalizeDeoptInfo(code);
      graph_compiler.FinalizeStackmaps(code);
      graph_compiler.FinalizeVarDescriptors(code);
      graph_compiler.FinalizeExceptionHandlers(code);
      graph_compiler.FinalizeComments(code);
      graph_compiler.FinalizeStaticCallTargetsTable(code);

      if (optimized) {
        CodePatcher::PatchEntry(Code::Handle(function.CurrentCode()));
        function.SetCode(code);
        if (FLAG_trace_compiler) {
          OS::Print("--> patching entry %#"Px"\n",
                    Code::Handle(function.unoptimized_code()).EntryPoint());
        }

        for (intptr_t i = 0; i < guarded_fields.length(); i++) {
          const Field& field = *guarded_fields[i];
          field.RegisterDependentCode(code);
        }
      } else {
        function.set_unoptimized_code(code);
        function.SetCode(code);
        ASSERT(CodePatcher::CodeIsPatchable(code));
      }
    }
    is_compiled = true;
  } else {
    // We bailed out.
    Error& bailout_error = Error::Handle(
        isolate->object_store()->sticky_error());
    isolate->object_store()->clear_sticky_error();
    if (FLAG_trace_bailout) {
      OS::Print("%s\n", bailout_error.ToErrorCString());
    }
    // We only bail out from generating ssa code.
    ASSERT(optimized);
    is_compiled = false;
  }
  // Reset global isolate state.
  isolate->set_ic_data_array(Array::null());
  isolate->set_long_jump_base(old_base);
  isolate->set_deopt_id(prev_deopt_id);
  return is_compiled;
}


static void DisassembleCode(const Function& function, bool optimized) {
  const char* function_fullname = function.ToFullyQualifiedCString();
  OS::Print("Code for %sfunction '%s' {\n",
            optimized ? "optimized " : "",
            function_fullname);
  const Code& code = Code::Handle(function.CurrentCode());
  const Instructions& instructions =
      Instructions::Handle(code.instructions());
  uword start = instructions.EntryPoint();
  Disassembler::Disassemble(start,
                            start + instructions.size(),
                            code.comments());
  OS::Print("}\n");

  OS::Print("Pointer offsets for function: {\n");
  // Pointer offsets are stored in descending order.
  for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) {
    const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint();
    Object& obj = Object::Handle();
    obj = *reinterpret_cast<RawObject**>(addr);
    OS::Print(" %d : %#"Px" '%s'\n",
              code.GetPointerOffsetAt(i), addr, obj.ToCString());
  }
  OS::Print("}\n");

  OS::Print("PC Descriptors for function '%s' {\n", function_fullname);
  PcDescriptors::PrintHeaderString();
  const PcDescriptors& descriptors =
      PcDescriptors::Handle(code.pc_descriptors());
  OS::Print("%s}\n", descriptors.ToCString());

  const Array& deopt_table = Array::Handle(code.deopt_info_array());
  intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table);
  if (deopt_table_length > 0) {
    OS::Print("DeoptInfo: {\n");
    Smi& offset = Smi::Handle();
    DeoptInfo& info = DeoptInfo::Handle();
    Smi& reason = Smi::Handle();
    for (intptr_t i = 0; i < deopt_table_length; ++i) {
      DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason);
      OS::Print("%4"Pd": 0x%"Px"  %s  (%s)\n",
                i,
                start + offset.Value(),
                info.ToCString(),
                DeoptReasonToText(reason.Value()));
    }
    OS::Print("}\n");
  }

  const Array& object_table = Array::Handle(code.object_table());
  if (object_table.Length() > 0) {
    OS::Print("Object Table: {\n");
    for (intptr_t i = 0; i < object_table.Length(); i++) {
      OS::Print("  %"Pd": %s\n", i,
          Object::Handle(object_table.At(i)).ToCString());
    }
    OS::Print("}\n");
  }

  OS::Print("Stackmaps for function '%s' {\n", function_fullname);
  if (code.stackmaps() != Array::null()) {
    const Array& stackmap_table = Array::Handle(code.stackmaps());
    Stackmap& map = Stackmap::Handle();
    for (intptr_t i = 0; i < stackmap_table.Length(); ++i) {
      map ^= stackmap_table.At(i);
      OS::Print("%s\n", map.ToCString());
    }
  }
  OS::Print("}\n");

  OS::Print("Variable Descriptors for function '%s' {\n",
            function_fullname);
  const LocalVarDescriptors& var_descriptors =
      LocalVarDescriptors::Handle(code.var_descriptors());
  intptr_t var_desc_length =
      var_descriptors.IsNull() ? 0 : var_descriptors.Length();
  String& var_name = String::Handle();
  for (intptr_t i = 0; i < var_desc_length; i++) {
    var_name = var_descriptors.GetName(i);
    RawLocalVarDescriptors::VarInfo var_info;
    var_descriptors.GetInfo(i, &var_info);
    if (var_info.kind == RawLocalVarDescriptors::kContextChain) {
      OS::Print("  saved CTX reg offset %"Pd"\n", var_info.index);
    } else {
      if (var_info.kind == RawLocalVarDescriptors::kContextLevel) {
        OS::Print("  context level %"Pd" scope %d",
                  var_info.index, var_info.scope_id);
      } else if (var_info.kind == RawLocalVarDescriptors::kStackVar) {
        OS::Print("  stack var '%s' offset %"Pd"",
                  var_name.ToCString(), var_info.index);
      } else {
        ASSERT(var_info.kind == RawLocalVarDescriptors::kContextVar);
        OS::Print("  context var '%s' level %d offset %"Pd"",
                  var_name.ToCString(), var_info.scope_id, var_info.index);
      }
      OS::Print(" (valid %"Pd"-%"Pd")\n",
                var_info.begin_pos, var_info.end_pos);
    }
  }
  OS::Print("}\n");

  OS::Print("Exception Handlers for function '%s' {\n", function_fullname);
  const ExceptionHandlers& handlers =
        ExceptionHandlers::Handle(code.exception_handlers());
  OS::Print("%s}\n", handlers.ToCString());

  {
    OS::Print("Static call target functions {\n");
    const Array& table = Array::Handle(code.static_calls_target_table());
    Smi& offset = Smi::Handle();
    Function& function = Function::Handle();
    Code& code = Code::Handle();
    for (intptr_t i = 0; i < table.Length();
        i += Code::kSCallTableEntryLength) {
      offset ^= table.At(i + Code::kSCallTableOffsetEntry);
      function ^= table.At(i + Code::kSCallTableFunctionEntry);
      code ^= table.At(i + Code::kSCallTableCodeEntry);
      OS::Print("  0x%"Px": %s, %p\n",
          start + offset.Value(),
          function.ToFullyQualifiedCString(),
          code.raw());
    }
    OS::Print("}\n");
  }
}


static RawError* CompileFunctionHelper(const Function& function,
                                       bool optimized) {
  Isolate* isolate = Isolate::Current();
  StackZone zone(isolate);
  LongJump* base = isolate->long_jump_base();
  LongJump jump;
  isolate->set_long_jump_base(&jump);
  // Skips parsing if we need to only install unoptimized code.
  if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) {
    InstallUnoptimizedCode(function);
    isolate->set_long_jump_base(base);
    return Error::null();
  }
  if (setjmp(*jump.Set()) == 0) {
    TIMERSCOPE(time_compilation);
    Timer per_compile_timer(FLAG_trace_compiler, "Compilation time");
    per_compile_timer.Start();
    ParsedFunction* parsed_function = new ParsedFunction(
        Function::ZoneHandle(function.raw()));
    if (FLAG_trace_compiler) {
      OS::Print("Compiling %sfunction: '%s' @ token %"Pd", size %"Pd"\n",
                (optimized ? "optimized " : ""),
                function.ToFullyQualifiedCString(),
                function.token_pos(),
                (function.end_token_pos() - function.token_pos()));
    }
    {
      HANDLESCOPE(isolate);
      Parser::ParseFunction(parsed_function);
      parsed_function->AllocateVariables();
    }

    const bool success =
        CompileParsedFunctionHelper(*parsed_function, optimized);
    if (optimized && !success) {
      // Optimizer bailed out. Disable optimizations and to never try again.
      if (FLAG_trace_compiler) {
        OS::Print("--> disabling optimizations for '%s'\n",
                  function.ToFullyQualifiedCString());
      } else if (FLAG_trace_failed_optimization_attempts) {
        OS::Print("Cannot optimize: %s\n", function.ToFullyQualifiedCString());
      }
      function.set_is_optimizable(false);
      isolate->set_long_jump_base(base);
      return Error::null();
    }

    ASSERT(success);
    per_compile_timer.Stop();

    if (FLAG_trace_compiler) {
      OS::Print("--> '%s' entry: %#"Px" size: %"Pd" time: %"Pd64" us\n",
                function.ToFullyQualifiedCString(),
                Code::Handle(function.CurrentCode()).EntryPoint(),
                Code::Handle(function.CurrentCode()).Size(),
                per_compile_timer.TotalElapsedTime());
    }

    isolate->debugger()->NotifyCompilation(function);

    if (FLAG_disassemble) {
      DisassembleCode(function, optimized);
    } else if (FLAG_disassemble_optimized && optimized) {
      // TODO(fschneider): Print unoptimized code along with the optimized code.
      OS::Print("*** BEGIN CODE\n");
      DisassembleCode(function, true);
      OS::Print("*** END CODE\n");
    }

    isolate->set_long_jump_base(base);
    return Error::null();
  } else {
    Error& error = Error::Handle();
    // We got an error during compilation.
    error = isolate->object_store()->sticky_error();
    isolate->object_store()->clear_sticky_error();
    isolate->set_long_jump_base(base);
    return error.raw();
  }
  UNREACHABLE();
  return Error::null();
}


RawError* Compiler::CompileFunction(const Function& function) {
  return CompileFunctionHelper(function, false);  // Non-optimized.
}


RawError* Compiler::CompileOptimizedFunction(const Function& function) {
  return CompileFunctionHelper(function, true);  // Optimized.
}


RawError* Compiler::CompileParsedFunction(
    const ParsedFunction& parsed_function) {
  Isolate* isolate = Isolate::Current();
  LongJump* base = isolate->long_jump_base();
  LongJump jump;
  isolate->set_long_jump_base(&jump);
  if (setjmp(*jump.Set()) == 0) {
    // Non-optimized code generator.
    CompileParsedFunctionHelper(parsed_function, false);
    if (FLAG_disassemble) {
      DisassembleCode(parsed_function.function(), false);
    }
    isolate->set_long_jump_base(base);
    return Error::null();
  } else {
    Error& error = Error::Handle();
    // We got an error during compilation.
    error = isolate->object_store()->sticky_error();
    isolate->object_store()->clear_sticky_error();
    isolate->set_long_jump_base(base);
    return error.raw();
  }
  UNREACHABLE();
  return Error::null();
}


RawError* Compiler::CompileAllFunctions(const Class& cls) {
  Error& error = Error::Handle();
  Array& functions = Array::Handle(cls.functions());
  Function& func = Function::Handle();
  // Class dynamic lives in the vm isolate. Its array fields cannot be set to
  // an empty array.
  if (functions.IsNull()) {
    ASSERT(cls.IsDynamicClass());
    return error.raw();
  }
  for (int i = 0; i < functions.Length(); i++) {
    func ^= functions.At(i);
    ASSERT(!func.IsNull());
    if (!func.HasCode() &&
        !func.is_abstract() &&
        !func.IsRedirectingFactory()) {
      error = CompileFunction(func);
      if (!error.IsNull()) {
        return error.raw();
      }
    }
  }
  return error.raw();
}


RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) {
  Isolate* isolate = Isolate::Current();
  LongJump* base = isolate->long_jump_base();
  LongJump jump;
  isolate->set_long_jump_base(&jump);
  if (setjmp(*jump.Set()) == 0) {
    if (FLAG_trace_compiler) {
      OS::Print("compiling expression: ");
      AstPrinter::PrintNode(fragment);
    }

    // Create a dummy function object for the code generator.
    // The function needs to be associated with a named Class: the interface
    // Function fits the bill.
    const char* kEvalConst = "eval_const";
    const Function& func = Function::ZoneHandle(Function::New(
        String::Handle(Symbols::New(kEvalConst)),
        RawFunction::kConstImplicitGetter,
        true,  // static function.
        false,  // not const function.
        false,  // not abstract
        false,  // not external.
        Class::Handle(Type::Handle(Type::Function()).type_class()),
        fragment->token_pos()));

    func.set_result_type(Type::Handle(Type::DynamicType()));
    func.set_num_fixed_parameters(0);
    func.SetNumOptionalParameters(0, true);
    // Manually generated AST, do not recompile.
    func.set_is_optimizable(false);

    // We compile the function here, even though InvokeStatic() below
    // would compile func automatically. We are checking fewer invariants
    // here.
    ParsedFunction* parsed_function = new ParsedFunction(func);
    parsed_function->SetNodeSequence(fragment);
    parsed_function->set_default_parameter_values(Array::ZoneHandle());
    parsed_function->set_expression_temp_var(
        ParsedFunction::CreateExpressionTempVar(0));
    fragment->scope()->AddVariable(parsed_function->expression_temp_var());
    parsed_function->set_array_literal_var(
        ParsedFunction::CreateArrayLiteralVar(0));
    fragment->scope()->AddVariable(parsed_function->array_literal_var());
    parsed_function->AllocateVariables();

    // Non-optimized code generator.
    CompileParsedFunctionHelper(*parsed_function, false);

    const Object& result = Object::Handle(
        DartEntry::InvokeFunction(func, Object::empty_array()));
    isolate->set_long_jump_base(base);
    return result.raw();
  } else {
    const Object& result =
      Object::Handle(isolate->object_store()->sticky_error());
    isolate->object_store()->clear_sticky_error();
    isolate->set_long_jump_base(base);
    return result.raw();
  }
  UNREACHABLE();
  return Object::null();
}

}  // namespace dart
