| Index: runtime/vm/compiler.cc
|
| diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
|
| index 0a452b337b1a412b47d1b82ca76ea63fc7d60420..874a2aebfb307a4a2f6c5524021a00a02921e51a 100644
|
| --- a/runtime/vm/compiler.cc
|
| +++ b/runtime/vm/compiler.cc
|
| @@ -204,14 +204,14 @@ CompilationPipeline* CompilationPipeline::New(Zone* zone,
|
| DEFINE_RUNTIME_ENTRY(CompileFunction, 1) {
|
| const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
|
| ASSERT(!function.HasCode());
|
| - const Error& error =
|
| - Error::Handle(Compiler::CompileFunction(thread, function));
|
| - if (!error.IsNull()) {
|
| - if (error.IsLanguageError()) {
|
| - Exceptions::ThrowCompileTimeError(LanguageError::Cast(error));
|
| + const Object& result =
|
| + Object::Handle(Compiler::CompileFunction(thread, function));
|
| + if (result.IsError()) {
|
| + if (result.IsLanguageError()) {
|
| + Exceptions::ThrowCompileTimeError(LanguageError::Cast(result));
|
| UNREACHABLE();
|
| }
|
| - Exceptions::PropagateError(error);
|
| + Exceptions::PropagateError(Error::Cast(result));
|
| }
|
| }
|
|
|
| @@ -496,7 +496,7 @@ class CompileParsedFunctionHelper : public ValueObject {
|
| loading_invalidation_gen_at_start_(
|
| isolate()->loading_invalidation_gen()) {}
|
|
|
| - bool Compile(CompilationPipeline* pipeline);
|
| + RawCode* Compile(CompilationPipeline* pipeline);
|
|
|
| private:
|
| ParsedFunction* parsed_function() const { return parsed_function_; }
|
| @@ -507,9 +507,9 @@ class CompileParsedFunctionHelper : public ValueObject {
|
| intptr_t loading_invalidation_gen_at_start() const {
|
| return loading_invalidation_gen_at_start_;
|
| }
|
| - void FinalizeCompilation(Assembler* assembler,
|
| - FlowGraphCompiler* graph_compiler,
|
| - FlowGraph* flow_graph);
|
| + RawCode* FinalizeCompilation(Assembler* assembler,
|
| + FlowGraphCompiler* graph_compiler,
|
| + FlowGraph* flow_graph);
|
| void CheckIfBackgroundCompilerIsBeingStopped();
|
|
|
| ParsedFunction* parsed_function_;
|
| @@ -522,7 +522,7 @@ class CompileParsedFunctionHelper : public ValueObject {
|
| };
|
|
|
|
|
| -void CompileParsedFunctionHelper::FinalizeCompilation(
|
| +RawCode* CompileParsedFunctionHelper::FinalizeCompilation(
|
| Assembler* assembler,
|
| FlowGraphCompiler* graph_compiler,
|
| FlowGraph* flow_graph) {
|
| @@ -539,7 +539,7 @@ void CompileParsedFunctionHelper::FinalizeCompilation(
|
| deopt_info_array.Length() * sizeof(uword));
|
| // Allocates instruction object. Since this occurs only at safepoint,
|
| // there can be no concurrent access to the instruction page.
|
| - const Code& code =
|
| + Code& code =
|
| Code::Handle(Code::FinalizeCode(function, assembler, optimized()));
|
| code.set_is_optimized(optimized());
|
| code.set_owner(function);
|
| @@ -588,12 +588,13 @@ void CompileParsedFunctionHelper::FinalizeCompilation(
|
| graph_compiler->FinalizeCodeSourceMap(code);
|
|
|
| if (optimized()) {
|
| - bool code_was_installed = false;
|
| // Installs code while at safepoint.
|
| if (thread()->IsMutatorThread()) {
|
| const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
|
| - function.InstallOptimizedCode(code, is_osr);
|
| - code_was_installed = true;
|
| + if (!is_osr) {
|
| + function.InstallOptimizedCode(code);
|
| + }
|
| + ASSERT(code.owner() == function.raw());
|
| } else {
|
| // Background compilation.
|
| // Before installing code check generation counts if the code may
|
| @@ -637,8 +638,9 @@ void CompileParsedFunctionHelper::FinalizeCompilation(
|
| if (code_is_valid && Compiler::CanOptimizeFunction(thread(), function)) {
|
| const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
|
| ASSERT(!is_osr); // OSR is not compiled in background.
|
| - function.InstallOptimizedCode(code, is_osr);
|
| - code_was_installed = true;
|
| + function.InstallOptimizedCode(code);
|
| + } else {
|
| + code = Code::null();
|
| }
|
| if (function.usage_counter() < 0) {
|
| // Reset to 0 so that it can be recompiled if needed.
|
| @@ -651,7 +653,7 @@ void CompileParsedFunctionHelper::FinalizeCompilation(
|
| }
|
| }
|
|
|
| - if (code_was_installed) {
|
| + if (!code.IsNull()) {
|
| // The generated code was compiled under certain assumptions about
|
| // class hierarchy and field types. Register these dependencies
|
| // to ensure that the code will be deoptimized if they are violated.
|
| @@ -682,6 +684,7 @@ void CompileParsedFunctionHelper::FinalizeCompilation(
|
| (*prefixes)[i]->RegisterDependentCode(code);
|
| }
|
| }
|
| + return code.raw();
|
| }
|
|
|
|
|
| @@ -695,16 +698,15 @@ void CompileParsedFunctionHelper::CheckIfBackgroundCompilerIsBeingStopped() {
|
| }
|
|
|
|
|
| -// Return false if bailed out.
|
| +// Return null if bailed out.
|
| // If optimized_result_code is not NULL then it is caller's responsibility
|
| // to install code.
|
| -bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| +RawCode* CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| ASSERT(!FLAG_precompiled_mode);
|
| const Function& function = parsed_function()->function();
|
| if (optimized() && !function.IsOptimizable()) {
|
| - return false;
|
| + return Code::null();
|
| }
|
| - bool is_compiled = false;
|
| Zone* const zone = thread()->zone();
|
| NOT_IN_PRODUCT(TimelineStream* compiler_timeline =
|
| Timeline::GetCompilerStream());
|
| @@ -722,12 +724,13 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| volatile bool use_far_branches = false;
|
| const bool use_speculative_inlining = false;
|
|
|
| + Code* volatile result = &Code::ZoneHandle(zone);
|
| while (!done) {
|
| + *result = Code::null();
|
| const intptr_t prev_deopt_id = thread()->deopt_id();
|
| thread()->set_deopt_id(0);
|
| LongJumpScope jump;
|
| - const intptr_t val = setjmp(*jump.Set());
|
| - if (val == 0) {
|
| + if (setjmp(*jump.Set()) == 0) {
|
| FlowGraph* flow_graph = NULL;
|
|
|
| // Class hierarchy analysis is registered with the thread in the
|
| @@ -1135,7 +1138,8 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| NOT_IN_PRODUCT(TimelineDurationScope tds(thread(), compiler_timeline,
|
| "FinalizeCompilation"));
|
| if (thread()->IsMutatorThread()) {
|
| - FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
|
| + *result =
|
| + FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
|
| } else {
|
| // This part of compilation must be at a safepoint.
|
| // Stop mutator thread before creating the instruction object and
|
| @@ -1151,7 +1155,8 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| // heap to grow.
|
| NoHeapGrowthControlScope no_growth_control;
|
| CheckIfBackgroundCompilerIsBeingStopped();
|
| - FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
|
| + *result =
|
| + FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
|
| }
|
| // TODO(srdjan): Enable this and remove the one from
|
| // 'BackgroundCompiler::CompileOptimized' once cause of time-outs
|
| @@ -1162,7 +1167,6 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| }
|
| }
|
| // Exit the loop and the function with the correct result value.
|
| - is_compiled = true;
|
| done = true;
|
| } else {
|
| // We bailed out or we encountered an error.
|
| @@ -1179,8 +1183,7 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| UNREACHABLE();
|
| } else {
|
| // If the error isn't due to an out of range branch offset, we don't
|
| - // try again (done = true), and indicate that we did not finish
|
| - // compiling (is_compiled = false).
|
| + // try again (done = true).
|
| if (FLAG_trace_bailout) {
|
| THR_Print("%s\n", error.ToErrorCString());
|
| }
|
| @@ -1194,19 +1197,18 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| (LanguageError::Cast(error).kind() == Report::kBailout)) {
|
| thread()->clear_sticky_error();
|
| }
|
| - is_compiled = false;
|
| }
|
| // Reset global isolate state.
|
| thread()->set_deopt_id(prev_deopt_id);
|
| }
|
| - return is_compiled;
|
| + return result->raw();
|
| }
|
|
|
|
|
| -static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
|
| - const Function& function,
|
| - bool optimized,
|
| - intptr_t osr_id) {
|
| +static RawObject* CompileFunctionHelper(CompilationPipeline* pipeline,
|
| + const Function& function,
|
| + bool optimized,
|
| + intptr_t osr_id) {
|
| ASSERT(!FLAG_precompiled_mode);
|
| ASSERT(!optimized || function.was_compiled());
|
| LongJumpScope jump;
|
| @@ -1262,8 +1264,8 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
|
| }
|
| }
|
|
|
| - const bool success = helper.Compile(pipeline);
|
| - if (success) {
|
| + const Code& result = Code::Handle(helper.Compile(pipeline));
|
| + if (!result.IsNull()) {
|
| if (!optimized) {
|
| function.set_was_compiled(true);
|
| }
|
| @@ -1305,6 +1307,7 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
|
| function.SetIsOptimizable(false);
|
| return Error::null();
|
| } else {
|
| + ASSERT(!optimized);
|
| // Encountered error.
|
| Error& error = Error::Handle();
|
| // We got an error during compilation.
|
| @@ -1318,11 +1321,12 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
|
| LanguageError::Cast(error).kind() != Report::kBailout));
|
| return error.raw();
|
| }
|
| + UNREACHABLE();
|
| }
|
|
|
| per_compile_timer.Stop();
|
|
|
| - if (trace_compiler && success) {
|
| + if (trace_compiler) {
|
| THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n",
|
| function.ToFullyQualifiedCString(),
|
| Code::Handle(function.CurrentCode()).PayloadStart(),
|
| @@ -1341,7 +1345,7 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
|
| Disassembler::DisassembleCode(function, true);
|
| }
|
|
|
| - return Error::null();
|
| + return result.raw();
|
| } else {
|
| Thread* const thread = Thread::Current();
|
| StackZone stack_zone(thread);
|
| @@ -1356,14 +1360,14 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
|
| THR_Print("Aborted background compilation: %s\n",
|
| function.ToFullyQualifiedCString());
|
| }
|
| - return Error::null();
|
| + return Object::null();
|
| }
|
| // Do not attempt to optimize functions that can cause errors.
|
| function.set_is_optimizable(false);
|
| return error.raw();
|
| }
|
| UNREACHABLE();
|
| - return Error::null();
|
| + return Object::null();
|
| }
|
|
|
|
|
| @@ -1424,7 +1428,7 @@ static RawError* ParseFunctionHelper(CompilationPipeline* pipeline,
|
| }
|
|
|
|
|
| -RawError* Compiler::CompileFunction(Thread* thread, const Function& function) {
|
| +RawObject* Compiler::CompileFunction(Thread* thread, const Function& function) {
|
| #ifdef DART_PRECOMPILER
|
| if (FLAG_precompiled_mode) {
|
| return Precompiler::CompileFunction(
|
| @@ -1487,19 +1491,20 @@ RawError* Compiler::EnsureUnoptimizedCode(Thread* thread,
|
| }
|
| CompilationPipeline* pipeline =
|
| CompilationPipeline::New(thread->zone(), function);
|
| - const Error& error = Error::Handle(
|
| + const Object& result = Object::Handle(
|
| CompileFunctionHelper(pipeline, function, false, /* not optimized */
|
| kNoOSRDeoptId));
|
| - if (!error.IsNull()) {
|
| - return error.raw();
|
| + if (result.IsError()) {
|
| + return Error::Cast(result).raw();
|
| }
|
| // Since CompileFunctionHelper replaces the current code, re-attach the
|
| // the original code if the function was already compiled.
|
| - if (!original_code.IsNull() &&
|
| - (original_code.raw() != function.CurrentCode())) {
|
| + if (!original_code.IsNull() && result.raw() == function.CurrentCode() &&
|
| + !original_code.IsDisabled()) {
|
| function.AttachCode(original_code);
|
| }
|
| ASSERT(function.unoptimized_code() != Object::null());
|
| + ASSERT(function.unoptimized_code() == result.raw());
|
| if (FLAG_trace_compiler) {
|
| THR_Print("Ensure unoptimized code for %s\n", function.ToCString());
|
| }
|
| @@ -1507,9 +1512,9 @@ RawError* Compiler::EnsureUnoptimizedCode(Thread* thread,
|
| }
|
|
|
|
|
| -RawError* Compiler::CompileOptimizedFunction(Thread* thread,
|
| - const Function& function,
|
| - intptr_t osr_id) {
|
| +RawObject* Compiler::CompileOptimizedFunction(Thread* thread,
|
| + const Function& function,
|
| + intptr_t osr_id) {
|
| #if !defined(PRODUCT)
|
| VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId);
|
| const char* event_name;
|
| @@ -1592,14 +1597,14 @@ void Compiler::ComputeLocalVarDescriptors(const Code& code) {
|
| RawError* Compiler::CompileAllFunctions(const Class& cls) {
|
| Thread* thread = Thread::Current();
|
| Zone* zone = thread->zone();
|
| - Error& error = Error::Handle(zone);
|
| + Object& result = Object::Handle(zone);
|
| Array& functions = Array::Handle(zone, cls.functions());
|
| Function& func = Function::Handle(zone);
|
| // 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();
|
| + return Error::null();
|
| }
|
| // Compile all the regular functions.
|
| for (int i = 0; i < functions.Length(); i++) {
|
| @@ -1612,15 +1617,16 @@ RawError* Compiler::CompileAllFunctions(const Class& cls) {
|
| // Skipping optional parameters in mixin application.
|
| continue;
|
| }
|
| - error = CompileFunction(thread, func);
|
| - if (!error.IsNull()) {
|
| - return error.raw();
|
| + result = CompileFunction(thread, func);
|
| + if (result.IsError()) {
|
| + return Error::Cast(result).raw();
|
| }
|
| + ASSERT(!result.IsNull());
|
| func.ClearICDataArray();
|
| func.ClearCode();
|
| }
|
| }
|
| - return error.raw();
|
| + return Error::null();
|
| }
|
|
|
|
|
| @@ -2197,7 +2203,7 @@ RawError* Compiler::CompileClass(const Class& cls) {
|
| }
|
|
|
|
|
| -RawError* Compiler::CompileFunction(Thread* thread, const Function& function) {
|
| +RawObject* Compiler::CompileFunction(Thread* thread, const Function& function) {
|
| UNREACHABLE();
|
| return Error::null();
|
| }
|
| @@ -2216,9 +2222,9 @@ RawError* Compiler::EnsureUnoptimizedCode(Thread* thread,
|
| }
|
|
|
|
|
| -RawError* Compiler::CompileOptimizedFunction(Thread* thread,
|
| - const Function& function,
|
| - intptr_t osr_id) {
|
| +RawObject* Compiler::CompileOptimizedFunction(Thread* thread,
|
| + const Function& function,
|
| + intptr_t osr_id) {
|
| UNREACHABLE();
|
| return Error::null();
|
| }
|
|
|