| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/compiler.h" | 5 #include "vm/compiler.h" |
| 6 | 6 |
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 | 8 |
| 9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
| 10 #include "vm/code_generator.h" | 10 #include "vm/code_generator.h" |
| 11 #include "vm/code_patcher.h" | 11 #include "vm/code_patcher.h" |
| 12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
| 13 #include "vm/debugger.h" | 13 #include "vm/debugger.h" |
| 14 #include "vm/deopt_instructions.h" | 14 #include "vm/deopt_instructions.h" |
| 15 #include "vm/disassembler.h" |
| 15 #include "vm/exceptions.h" | 16 #include "vm/exceptions.h" |
| 16 #include "vm/flags.h" | 17 #include "vm/flags.h" |
| 17 #include "vm/flow_graph.h" | 18 #include "vm/flow_graph.h" |
| 18 #include "vm/flow_graph_allocator.h" | 19 #include "vm/flow_graph_allocator.h" |
| 19 #include "vm/flow_graph_builder.h" | 20 #include "vm/flow_graph_builder.h" |
| 20 #include "vm/flow_graph_compiler.h" | 21 #include "vm/flow_graph_compiler.h" |
| 21 #include "vm/flow_graph_inliner.h" | 22 #include "vm/flow_graph_inliner.h" |
| 22 #include "vm/flow_graph_optimizer.h" | 23 #include "vm/flow_graph_optimizer.h" |
| 23 #include "vm/flow_graph_type_propagator.h" | 24 #include "vm/flow_graph_type_propagator.h" |
| 24 #include "vm/il_printer.h" | 25 #include "vm/il_printer.h" |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 function.SwitchToUnoptimizedCode(); | 234 function.SwitchToUnoptimizedCode(); |
| 234 if (FLAG_trace_compiler) { | 235 if (FLAG_trace_compiler) { |
| 235 OS::Print("--> restoring entry at %#"Px"\n", | 236 OS::Print("--> restoring entry at %#"Px"\n", |
| 236 Code::Handle(function.unoptimized_code()).EntryPoint()); | 237 Code::Handle(function.unoptimized_code()).EntryPoint()); |
| 237 } | 238 } |
| 238 } | 239 } |
| 239 | 240 |
| 240 | 241 |
| 241 // Return false if bailed out. | 242 // Return false if bailed out. |
| 242 static bool CompileParsedFunctionHelper(ParsedFunction* parsed_function, | 243 static bool CompileParsedFunctionHelper(ParsedFunction* parsed_function, |
| 243 bool optimized, | 244 bool optimized) { |
| 244 intptr_t osr_id) { | |
| 245 const Function& function = parsed_function->function(); | 245 const Function& function = parsed_function->function(); |
| 246 if (optimized && !function.is_optimizable()) { | 246 if (optimized && !function.is_optimizable()) { |
| 247 return false; | 247 return false; |
| 248 } | 248 } |
| 249 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); | 249 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); |
| 250 bool is_compiled = false; | 250 bool is_compiled = false; |
| 251 Isolate* isolate = Isolate::Current(); | 251 Isolate* isolate = Isolate::Current(); |
| 252 HANDLESCOPE(isolate); | 252 HANDLESCOPE(isolate); |
| 253 const intptr_t prev_deopt_id = isolate->deopt_id(); | 253 const intptr_t prev_deopt_id = isolate->deopt_id(); |
| 254 isolate->set_deopt_id(0); | 254 isolate->set_deopt_id(0); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 274 FLAG_deoptimization_counter_threshold) { | 274 FLAG_deoptimization_counter_threshold) { |
| 275 const Code& unoptimized_code = | 275 const Code& unoptimized_code = |
| 276 Code::Handle(function.unoptimized_code()); | 276 Code::Handle(function.unoptimized_code()); |
| 277 ic_data_array = unoptimized_code.ExtractTypeFeedbackArray(); | 277 ic_data_array = unoptimized_code.ExtractTypeFeedbackArray(); |
| 278 } | 278 } |
| 279 } | 279 } |
| 280 | 280 |
| 281 // Build the flow graph. | 281 // Build the flow graph. |
| 282 FlowGraphBuilder builder(parsed_function, | 282 FlowGraphBuilder builder(parsed_function, |
| 283 ic_data_array, | 283 ic_data_array, |
| 284 NULL, // NULL = not inlining. | 284 NULL); // NULL = not inlining. |
| 285 osr_id); | |
| 286 flow_graph = builder.BuildGraph(); | 285 flow_graph = builder.BuildGraph(); |
| 287 } | 286 } |
| 288 | 287 |
| 289 if (FLAG_print_flow_graph || | 288 if (FLAG_print_flow_graph || |
| 290 (optimized && FLAG_print_flow_graph_optimized)) { | 289 (optimized && FLAG_print_flow_graph_optimized)) { |
| 291 if (osr_id == Isolate::kNoDeoptId) { | 290 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); |
| 292 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); | |
| 293 } else { | |
| 294 FlowGraphPrinter::PrintGraph("For OSR", flow_graph); | |
| 295 } | |
| 296 } | 291 } |
| 297 | 292 |
| 298 if (optimized) { | 293 if (optimized) { |
| 299 TimerScope timer(FLAG_compiler_stats, | 294 TimerScope timer(FLAG_compiler_stats, |
| 300 &CompilerStats::ssa_timer, | 295 &CompilerStats::ssa_timer, |
| 301 isolate); | 296 isolate); |
| 302 // Transform to SSA (virtual register 0 and no inlining arguments). | 297 // Transform to SSA (virtual register 0 and no inlining arguments). |
| 303 flow_graph->ComputeSSA(0, NULL); | 298 flow_graph->ComputeSSA(0, NULL); |
| 304 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 299 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 305 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { | 300 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 code.set_is_optimized(optimized); | 501 code.set_is_optimized(optimized); |
| 507 graph_compiler.FinalizePcDescriptors(code); | 502 graph_compiler.FinalizePcDescriptors(code); |
| 508 graph_compiler.FinalizeDeoptInfo(code); | 503 graph_compiler.FinalizeDeoptInfo(code); |
| 509 graph_compiler.FinalizeStackmaps(code); | 504 graph_compiler.FinalizeStackmaps(code); |
| 510 graph_compiler.FinalizeVarDescriptors(code); | 505 graph_compiler.FinalizeVarDescriptors(code); |
| 511 graph_compiler.FinalizeExceptionHandlers(code); | 506 graph_compiler.FinalizeExceptionHandlers(code); |
| 512 graph_compiler.FinalizeComments(code); | 507 graph_compiler.FinalizeComments(code); |
| 513 graph_compiler.FinalizeStaticCallTargetsTable(code); | 508 graph_compiler.FinalizeStaticCallTargetsTable(code); |
| 514 | 509 |
| 515 if (optimized) { | 510 if (optimized) { |
| 516 if (osr_id == Isolate::kNoDeoptId) { | 511 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); |
| 517 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); | 512 function.SetCode(code); |
| 518 if (FLAG_trace_compiler) { | 513 if (FLAG_trace_compiler) { |
| 519 OS::Print("--> patching entry %#"Px"\n", | 514 OS::Print("--> patching entry %#"Px"\n", |
| 520 Code::Handle(function.unoptimized_code()).EntryPoint()); | 515 Code::Handle(function.unoptimized_code()).EntryPoint()); |
| 521 } | |
| 522 } | 516 } |
| 523 function.SetCode(code); | |
| 524 | 517 |
| 525 for (intptr_t i = 0; i < guarded_fields.length(); i++) { | 518 for (intptr_t i = 0; i < guarded_fields.length(); i++) { |
| 526 const Field& field = *guarded_fields[i]; | 519 const Field& field = *guarded_fields[i]; |
| 527 field.RegisterDependentCode(code); | 520 field.RegisterDependentCode(code); |
| 528 } | 521 } |
| 529 } else { | 522 } else { |
| 530 function.set_unoptimized_code(code); | 523 function.set_unoptimized_code(code); |
| 531 function.SetCode(code); | 524 function.SetCode(code); |
| 532 ASSERT(CodePatcher::CodeIsPatchable(code)); | 525 ASSERT(CodePatcher::CodeIsPatchable(code)); |
| 533 } | 526 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 551 return is_compiled; | 544 return is_compiled; |
| 552 } | 545 } |
| 553 | 546 |
| 554 | 547 |
| 555 static void DisassembleCode(const Function& function, bool optimized) { | 548 static void DisassembleCode(const Function& function, bool optimized) { |
| 556 const char* function_fullname = function.ToFullyQualifiedCString(); | 549 const char* function_fullname = function.ToFullyQualifiedCString(); |
| 557 OS::Print("Code for %sfunction '%s' {\n", | 550 OS::Print("Code for %sfunction '%s' {\n", |
| 558 optimized ? "optimized " : "", | 551 optimized ? "optimized " : "", |
| 559 function_fullname); | 552 function_fullname); |
| 560 const Code& code = Code::Handle(function.CurrentCode()); | 553 const Code& code = Code::Handle(function.CurrentCode()); |
| 561 code.Disassemble(); | 554 const Instructions& instructions = |
| 555 Instructions::Handle(code.instructions()); |
| 556 uword start = instructions.EntryPoint(); |
| 557 Disassembler::Disassemble(start, |
| 558 start + instructions.size(), |
| 559 code.comments()); |
| 562 OS::Print("}\n"); | 560 OS::Print("}\n"); |
| 563 | 561 |
| 564 OS::Print("Pointer offsets for function: {\n"); | 562 OS::Print("Pointer offsets for function: {\n"); |
| 565 // Pointer offsets are stored in descending order. | 563 // Pointer offsets are stored in descending order. |
| 566 for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) { | 564 for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) { |
| 567 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); | 565 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); |
| 568 Object& obj = Object::Handle(); | 566 Object& obj = Object::Handle(); |
| 569 obj = *reinterpret_cast<RawObject**>(addr); | 567 obj = *reinterpret_cast<RawObject**>(addr); |
| 570 OS::Print(" %d : %#"Px" '%s'\n", | 568 OS::Print(" %d : %#"Px" '%s'\n", |
| 571 code.GetPointerOffsetAt(i), addr, obj.ToCString()); | 569 code.GetPointerOffsetAt(i), addr, obj.ToCString()); |
| 572 } | 570 } |
| 573 OS::Print("}\n"); | 571 OS::Print("}\n"); |
| 574 | 572 |
| 575 OS::Print("PC Descriptors for function '%s' {\n", function_fullname); | 573 OS::Print("PC Descriptors for function '%s' {\n", function_fullname); |
| 576 PcDescriptors::PrintHeaderString(); | 574 PcDescriptors::PrintHeaderString(); |
| 577 const PcDescriptors& descriptors = | 575 const PcDescriptors& descriptors = |
| 578 PcDescriptors::Handle(code.pc_descriptors()); | 576 PcDescriptors::Handle(code.pc_descriptors()); |
| 579 OS::Print("%s}\n", descriptors.ToCString()); | 577 OS::Print("%s}\n", descriptors.ToCString()); |
| 580 | 578 |
| 581 uword start = Instructions::Handle(code.instructions()).EntryPoint(); | |
| 582 const Array& deopt_table = Array::Handle(code.deopt_info_array()); | 579 const Array& deopt_table = Array::Handle(code.deopt_info_array()); |
| 583 intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table); | 580 intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table); |
| 584 if (deopt_table_length > 0) { | 581 if (deopt_table_length > 0) { |
| 585 OS::Print("DeoptInfo: {\n"); | 582 OS::Print("DeoptInfo: {\n"); |
| 586 Smi& offset = Smi::Handle(); | 583 Smi& offset = Smi::Handle(); |
| 587 DeoptInfo& info = DeoptInfo::Handle(); | 584 DeoptInfo& info = DeoptInfo::Handle(); |
| 588 Smi& reason = Smi::Handle(); | 585 Smi& reason = Smi::Handle(); |
| 589 for (intptr_t i = 0; i < deopt_table_length; ++i) { | 586 for (intptr_t i = 0; i < deopt_table_length; ++i) { |
| 590 DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason); | 587 DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason); |
| 591 OS::Print("%4"Pd": 0x%"Px" %s (%s)\n", | 588 OS::Print("%4"Pd": 0x%"Px" %s (%s)\n", |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 start + offset.Value(), | 668 start + offset.Value(), |
| 672 function.ToFullyQualifiedCString(), | 669 function.ToFullyQualifiedCString(), |
| 673 code.raw()); | 670 code.raw()); |
| 674 } | 671 } |
| 675 OS::Print("}\n"); | 672 OS::Print("}\n"); |
| 676 } | 673 } |
| 677 } | 674 } |
| 678 | 675 |
| 679 | 676 |
| 680 static RawError* CompileFunctionHelper(const Function& function, | 677 static RawError* CompileFunctionHelper(const Function& function, |
| 681 bool optimized, | 678 bool optimized) { |
| 682 intptr_t osr_id) { | |
| 683 Isolate* isolate = Isolate::Current(); | 679 Isolate* isolate = Isolate::Current(); |
| 684 StackZone zone(isolate); | 680 StackZone zone(isolate); |
| 685 LongJump* base = isolate->long_jump_base(); | 681 LongJump* base = isolate->long_jump_base(); |
| 686 LongJump jump; | 682 LongJump jump; |
| 687 isolate->set_long_jump_base(&jump); | 683 isolate->set_long_jump_base(&jump); |
| 688 // Skips parsing if we need to only install unoptimized code. | 684 // Skips parsing if we need to only install unoptimized code. |
| 689 if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) { | 685 if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) { |
| 690 InstallUnoptimizedCode(function); | 686 InstallUnoptimizedCode(function); |
| 691 isolate->set_long_jump_base(base); | 687 isolate->set_long_jump_base(base); |
| 692 return Error::null(); | 688 return Error::null(); |
| 693 } | 689 } |
| 694 if (setjmp(*jump.Set()) == 0) { | 690 if (setjmp(*jump.Set()) == 0) { |
| 695 TIMERSCOPE(time_compilation); | 691 TIMERSCOPE(time_compilation); |
| 696 Timer per_compile_timer(FLAG_trace_compiler, "Compilation time"); | 692 Timer per_compile_timer(FLAG_trace_compiler, "Compilation time"); |
| 697 per_compile_timer.Start(); | 693 per_compile_timer.Start(); |
| 698 ParsedFunction* parsed_function = new ParsedFunction( | 694 ParsedFunction* parsed_function = new ParsedFunction( |
| 699 Function::ZoneHandle(function.raw())); | 695 Function::ZoneHandle(function.raw())); |
| 700 if (FLAG_trace_compiler) { | 696 if (FLAG_trace_compiler) { |
| 701 OS::Print("Compiling %s%sfunction: '%s' @ token %"Pd", size %"Pd"\n", | 697 OS::Print("Compiling %sfunction: '%s' @ token %"Pd", size %"Pd"\n", |
| 702 (osr_id == Isolate::kNoDeoptId ? "" : "osr "), | |
| 703 (optimized ? "optimized " : ""), | 698 (optimized ? "optimized " : ""), |
| 704 function.ToFullyQualifiedCString(), | 699 function.ToFullyQualifiedCString(), |
| 705 function.token_pos(), | 700 function.token_pos(), |
| 706 (function.end_token_pos() - function.token_pos())); | 701 (function.end_token_pos() - function.token_pos())); |
| 707 } | 702 } |
| 708 { | 703 { |
| 709 HANDLESCOPE(isolate); | 704 HANDLESCOPE(isolate); |
| 710 Parser::ParseFunction(parsed_function); | 705 Parser::ParseFunction(parsed_function); |
| 711 parsed_function->AllocateVariables(); | 706 parsed_function->AllocateVariables(); |
| 712 } | 707 } |
| 713 | 708 |
| 714 const bool success = | 709 const bool success = |
| 715 CompileParsedFunctionHelper(parsed_function, optimized, osr_id); | 710 CompileParsedFunctionHelper(parsed_function, optimized); |
| 716 if (optimized && !success) { | 711 if (optimized && !success) { |
| 717 // Optimizer bailed out. Disable optimizations and to never try again. | 712 // Optimizer bailed out. Disable optimizations and to never try again. |
| 718 if (FLAG_trace_compiler) { | 713 if (FLAG_trace_compiler) { |
| 719 OS::Print("--> disabling optimizations for '%s'\n", | 714 OS::Print("--> disabling optimizations for '%s'\n", |
| 720 function.ToFullyQualifiedCString()); | 715 function.ToFullyQualifiedCString()); |
| 721 } else if (FLAG_trace_failed_optimization_attempts) { | 716 } else if (FLAG_trace_failed_optimization_attempts) { |
| 722 OS::Print("Cannot optimize: %s\n", function.ToFullyQualifiedCString()); | 717 OS::Print("Cannot optimize: %s\n", function.ToFullyQualifiedCString()); |
| 723 } | 718 } |
| 724 function.set_is_optimizable(false); | 719 function.set_is_optimizable(false); |
| 725 isolate->set_long_jump_base(base); | 720 isolate->set_long_jump_base(base); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 isolate->object_store()->clear_sticky_error(); | 752 isolate->object_store()->clear_sticky_error(); |
| 758 isolate->set_long_jump_base(base); | 753 isolate->set_long_jump_base(base); |
| 759 return error.raw(); | 754 return error.raw(); |
| 760 } | 755 } |
| 761 UNREACHABLE(); | 756 UNREACHABLE(); |
| 762 return Error::null(); | 757 return Error::null(); |
| 763 } | 758 } |
| 764 | 759 |
| 765 | 760 |
| 766 RawError* Compiler::CompileFunction(const Function& function) { | 761 RawError* Compiler::CompileFunction(const Function& function) { |
| 767 return CompileFunctionHelper(function, false, Isolate::kNoDeoptId); | 762 return CompileFunctionHelper(function, false); // Non-optimized. |
| 768 } | 763 } |
| 769 | 764 |
| 770 | 765 |
| 771 RawError* Compiler::CompileOptimizedFunction(const Function& function, | 766 RawError* Compiler::CompileOptimizedFunction(const Function& function) { |
| 772 intptr_t osr_id) { | 767 return CompileFunctionHelper(function, true); // Optimized. |
| 773 return CompileFunctionHelper(function, true, osr_id); | |
| 774 } | 768 } |
| 775 | 769 |
| 776 | 770 |
| 777 RawError* Compiler::CompileParsedFunction( | 771 RawError* Compiler::CompileParsedFunction( |
| 778 ParsedFunction* parsed_function) { | 772 ParsedFunction* parsed_function) { |
| 779 Isolate* isolate = Isolate::Current(); | 773 Isolate* isolate = Isolate::Current(); |
| 780 LongJump* base = isolate->long_jump_base(); | 774 LongJump* base = isolate->long_jump_base(); |
| 781 LongJump jump; | 775 LongJump jump; |
| 782 isolate->set_long_jump_base(&jump); | 776 isolate->set_long_jump_base(&jump); |
| 783 if (setjmp(*jump.Set()) == 0) { | 777 if (setjmp(*jump.Set()) == 0) { |
| 784 // Non-optimized code generator. | 778 // Non-optimized code generator. |
| 785 CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId); | 779 CompileParsedFunctionHelper(parsed_function, false); |
| 786 if (FLAG_disassemble) { | 780 if (FLAG_disassemble) { |
| 787 DisassembleCode(parsed_function->function(), false); | 781 DisassembleCode(parsed_function->function(), false); |
| 788 } | 782 } |
| 789 isolate->set_long_jump_base(base); | 783 isolate->set_long_jump_base(base); |
| 790 return Error::null(); | 784 return Error::null(); |
| 791 } else { | 785 } else { |
| 792 Error& error = Error::Handle(); | 786 Error& error = Error::Handle(); |
| 793 // We got an error during compilation. | 787 // We got an error during compilation. |
| 794 error = isolate->object_store()->sticky_error(); | 788 error = isolate->object_store()->sticky_error(); |
| 795 isolate->object_store()->clear_sticky_error(); | 789 isolate->object_store()->clear_sticky_error(); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 862 // would compile func automatically. We are checking fewer invariants | 856 // would compile func automatically. We are checking fewer invariants |
| 863 // here. | 857 // here. |
| 864 ParsedFunction* parsed_function = new ParsedFunction(func); | 858 ParsedFunction* parsed_function = new ParsedFunction(func); |
| 865 parsed_function->SetNodeSequence(fragment); | 859 parsed_function->SetNodeSequence(fragment); |
| 866 parsed_function->set_default_parameter_values(Array::ZoneHandle()); | 860 parsed_function->set_default_parameter_values(Array::ZoneHandle()); |
| 867 parsed_function->EnsureExpressionTemp(); | 861 parsed_function->EnsureExpressionTemp(); |
| 868 fragment->scope()->AddVariable(parsed_function->expression_temp_var()); | 862 fragment->scope()->AddVariable(parsed_function->expression_temp_var()); |
| 869 parsed_function->AllocateVariables(); | 863 parsed_function->AllocateVariables(); |
| 870 | 864 |
| 871 // Non-optimized code generator. | 865 // Non-optimized code generator. |
| 872 CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId); | 866 CompileParsedFunctionHelper(parsed_function, false); |
| 873 | 867 |
| 874 const Object& result = Object::Handle( | 868 const Object& result = Object::Handle( |
| 875 DartEntry::InvokeFunction(func, Object::empty_array())); | 869 DartEntry::InvokeFunction(func, Object::empty_array())); |
| 876 isolate->set_long_jump_base(base); | 870 isolate->set_long_jump_base(base); |
| 877 return result.raw(); | 871 return result.raw(); |
| 878 } else { | 872 } else { |
| 879 const Object& result = | 873 const Object& result = |
| 880 Object::Handle(isolate->object_store()->sticky_error()); | 874 Object::Handle(isolate->object_store()->sticky_error()); |
| 881 isolate->object_store()->clear_sticky_error(); | 875 isolate->object_store()->clear_sticky_error(); |
| 882 isolate->set_long_jump_base(base); | 876 isolate->set_long_jump_base(base); |
| 883 return result.raw(); | 877 return result.raw(); |
| 884 } | 878 } |
| 885 UNREACHABLE(); | 879 UNREACHABLE(); |
| 886 return Object::null(); | 880 return Object::null(); |
| 887 } | 881 } |
| 888 | 882 |
| 889 } // namespace dart | 883 } // namespace dart |
| OLD | NEW |