Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Side by Side Diff: vm/code_generator_ia32.cc

Issue 10375059: Use a reserved stack local variable to store the Code object so that it can be looked up easily whe… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/globals.h" // Needed here to get TARGET_ARCH_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
7 7
8 #include "vm/code_generator.h" 8 #include "vm/code_generator.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 __ popl(EDX); 178 __ popl(EDX);
179 __ popl(ECX); 179 __ popl(ECX);
180 } 180 }
181 181
182 const bool code_generation_finished = TryIntrinsify(); 182 const bool code_generation_finished = TryIntrinsify();
183 // In some cases intrinsifier can generate all code and no AST based 183 // In some cases intrinsifier can generate all code and no AST based
184 // code generation is needed. In some cases slow-paths (e.g., overflows) are 184 // code generation is needed. In some cases slow-paths (e.g., overflows) are
185 // implemented by the AST based code generation and 'code_generation_finished' 185 // implemented by the AST based code generation and 'code_generation_finished'
186 // is false. 186 // is false.
187 if (!code_generation_finished) { 187 if (!code_generation_finished) {
188 GeneratePreEntryCode();
189 GenerateEntryCode(); 188 GenerateEntryCode();
190 if (FLAG_print_scopes) { 189 if (FLAG_print_scopes) {
191 // Print the function scope (again) after generating the prologue in order 190 // Print the function scope (again) after generating the prologue in order
192 // to see annotations such as allocation indices of locals. 191 // to see annotations such as allocation indices of locals.
193 if (FLAG_print_ast) { 192 if (FLAG_print_ast) {
194 // Second printing. 193 // Second printing.
195 OS::Print("Annotated "); 194 OS::Print("Annotated ");
196 } 195 }
197 AstPrinter::PrintFunctionScope(parsed_function_); 196 AstPrinter::PrintFunctionScope(parsed_function_);
198 } 197 }
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 // 388 //
390 // TODO(regis): We may give up reserving space on stack for args/locals 389 // TODO(regis): We may give up reserving space on stack for args/locals
391 // because pushes of initial values may be more effective than moves. 390 // because pushes of initial values may be more effective than moves.
392 LocalScope* scope = parsed_function_.node_sequence()->scope(); 391 LocalScope* scope = parsed_function_.node_sequence()->scope();
393 const int num_fixed_params = function.num_fixed_parameters(); 392 const int num_fixed_params = function.num_fixed_parameters();
394 const int num_opt_params = function.num_optional_parameters(); 393 const int num_opt_params = function.num_optional_parameters();
395 const int num_copied_params = parsed_function_.copied_parameter_count(); 394 const int num_copied_params = parsed_function_.copied_parameter_count();
396 const int stack_slot_count = 395 const int stack_slot_count =
397 num_copied_params + parsed_function_.stack_local_count(); 396 num_copied_params + parsed_function_.stack_local_count();
398 set_locals_space_size(stack_slot_count * kWordSize); 397 set_locals_space_size(stack_slot_count * kWordSize);
399 __ EnterFrame(locals_space_size()); 398 AssemblerMacros::EnterDartFrame(assembler_, locals_space_size());
400 399
401 // 2. Optionally check if the number of arguments matches. We check the 400 // 2. Optionally check if the number of arguments matches. We check the
402 // number of passed arguments when we have to copy them due to the 401 // number of passed arguments when we have to copy them due to the
403 // presence of optional named parameters. No such checking code is 402 // presence of optional named parameters. No such checking code is
404 // generated if only fixed parameters are declared, unless we are in debug 403 // generated if only fixed parameters are declared, unless we are in debug
405 // mode or unless we are compiling a closure. 404 // mode or unless we are compiling a closure.
406 if (num_copied_params == 0) { 405 if (num_copied_params == 0) {
407 ASSERT(num_opt_params == 0); 406 ASSERT(num_opt_params == 0);
408 #if defined(DEBUG) 407 #if defined(DEBUG)
409 const bool check_arguments = true; // Always check arguments in debug mode. 408 const bool check_arguments = true; // Always check arguments in debug mode.
(...skipping 13 matching lines...) Expand all
423 if (function.IsClosureFunction()) { 422 if (function.IsClosureFunction()) {
424 GenerateCallRuntime(AstNode::kNoId, 423 GenerateCallRuntime(AstNode::kNoId,
425 0, 424 0,
426 kClosureArgumentMismatchRuntimeEntry); 425 kClosureArgumentMismatchRuntimeEntry);
427 } else { 426 } else {
428 __ Stop("Wrong number of arguments"); 427 __ Stop("Wrong number of arguments");
429 } 428 }
430 __ Bind(&argc_in_range); 429 __ Bind(&argc_in_range);
431 } 430 }
432 } else { 431 } else {
433 ASSERT(parsed_function_.first_parameter_index() == -1); 432 ASSERT(parsed_function_.first_parameter_index() ==
433 ParsedFunction::kFirstStackSlotIndex);
434 // Copy positional arguments. 434 // Copy positional arguments.
435 // Check that no fewer than num_fixed_params positional arguments are passed 435 // Check that no fewer than num_fixed_params positional arguments are passed
436 // in and that no more than num_params arguments are passed in. 436 // in and that no more than num_params arguments are passed in.
437 // Passed argument i at fp[1 + argc - i] copied to fp[-1 - i]. 437 // Passed argument i at fp[1 + argc - i] copied to
438 // fp[ParsedFunction::kFirstStackSlotIndex - i].
438 const int num_params = num_fixed_params + num_opt_params; 439 const int num_params = num_fixed_params + num_opt_params;
439 440
440 // Total number of args is the first Smi in args descriptor array (EDX). 441 // Total number of args is the first Smi in args descriptor array (EDX).
441 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); 442 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
442 // Check that num_args <= num_params. 443 // Check that num_args <= num_params.
443 Label wrong_num_arguments; 444 Label wrong_num_arguments;
444 __ cmpl(EBX, Immediate(Smi::RawValue(num_params))); 445 __ cmpl(EBX, Immediate(Smi::RawValue(num_params)));
445 __ j(GREATER, &wrong_num_arguments); 446 __ j(GREATER, &wrong_num_arguments);
446 // Number of positional args is the second Smi in descriptor array (EDX). 447 // Number of positional args is the second Smi in descriptor array (EDX).
447 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); 448 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
448 // Check that num_pos_args >= num_fixed_params. 449 // Check that num_pos_args >= num_fixed_params.
449 __ cmpl(ECX, Immediate(Smi::RawValue(num_fixed_params))); 450 __ cmpl(ECX, Immediate(Smi::RawValue(num_fixed_params)));
450 __ j(LESS, &wrong_num_arguments); 451 __ j(LESS, &wrong_num_arguments);
451 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4. 452 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4.
452 // Let EBX point to the last passed positional argument, i.e. to 453 // Let EBX point to the last passed positional argument, i.e. to
453 // fp[1 + num_args - (num_pos_args - 1)]. 454 // fp[1 + num_args - (num_pos_args - 1)].
454 __ subl(EBX, ECX); 455 __ subl(EBX, ECX);
455 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize)); 456 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize));
456 // Let EDI point to the last copied positional argument, i.e. to 457 // Let EDI point to the last copied positional argument, i.e. to
457 // fp[-1 - (num_pos_args - 1)]. 458 // fp[ParsedFunction::kFirstStackSlotIndex - (num_pos_args - 1)].
458 __ movl(EDI, EBP); 459 int index = ParsedFunction::kFirstStackSlotIndex + 1;
regis 2012/05/14 17:33:10 const
siva 2012/05/15 23:52:39 Done.
460 __ leal(EDI, Address(EBP, (index * kWordSize)));
459 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling. 461 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling.
460 __ subl(EDI, ECX); 462 __ subl(EDI, ECX);
461 __ SmiUntag(ECX); 463 __ SmiUntag(ECX);
462 Label loop, loop_condition; 464 Label loop, loop_condition;
463 __ jmp(&loop_condition, Assembler::kNearJump); 465 __ jmp(&loop_condition, Assembler::kNearJump);
464 // We do not use the final allocation index of the variable here, i.e. 466 // We do not use the final allocation index of the variable here, i.e.
465 // scope->VariableAt(i)->index(), because captured variables still need 467 // scope->VariableAt(i)->index(), because captured variables still need
466 // to be copied to the context that is not yet allocated. 468 // to be copied to the context that is not yet allocated.
467 const Address argument_addr(EBX, ECX, TIMES_4, 0); 469 const Address argument_addr(EBX, ECX, TIMES_4, 0);
468 const Address copy_addr(EDI, ECX, TIMES_4, 0); 470 const Address copy_addr(EDI, ECX, TIMES_4, 0);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi. 525 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi.
524 __ movl(EAX, argument_addr); 526 __ movl(EAX, argument_addr);
525 __ jmp(&assign_optional_parameter, Assembler::kNearJump); 527 __ jmp(&assign_optional_parameter, Assembler::kNearJump);
526 __ Bind(&load_default_value); 528 __ Bind(&load_default_value);
527 // Load EAX with default argument at pos. 529 // Load EAX with default argument at pos.
528 const Object& value = Object::ZoneHandle( 530 const Object& value = Object::ZoneHandle(
529 parsed_function_.default_parameter_values().At( 531 parsed_function_.default_parameter_values().At(
530 param_pos - num_fixed_params)); 532 param_pos - num_fixed_params));
531 __ LoadObject(EAX, value); 533 __ LoadObject(EAX, value);
532 __ Bind(&assign_optional_parameter); 534 __ Bind(&assign_optional_parameter);
533 // Assign EAX to fp[-1 - param_pos]. 535 // Assign EAX to fp[ParsedFunction::kFirstStackSlotIndex - param_pos].
534 // We do not use the final allocation index of the variable here, i.e. 536 // We do not use the final allocation index of the variable here, i.e.
535 // scope->VariableAt(i)->index(), because captured variables still need 537 // scope->VariableAt(i)->index(), because captured variables still need
536 // to be copied to the context that is not yet allocated. 538 // to be copied to the context that is not yet allocated.
537 const Address param_addr(EBP, (-1 - param_pos) * kWordSize); 539 const Address param_addr(
540 EBP, (ParsedFunction::kFirstStackSlotIndex - param_pos) * kWordSize);
538 __ movl(param_addr, EAX); 541 __ movl(param_addr, EAX);
539 __ Bind(&next_parameter); 542 __ Bind(&next_parameter);
540 } 543 }
541 delete[] opt_param; 544 delete[] opt_param;
542 delete[] opt_param_position; 545 delete[] opt_param_position;
543 // Check that EDI now points to the null terminator in the array descriptor. 546 // Check that EDI now points to the null terminator in the array descriptor.
544 Label all_arguments_processed; 547 Label all_arguments_processed;
545 __ cmpl(Address(EDI, 0), raw_null); 548 __ cmpl(Address(EDI, 0), raw_null);
546 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); 549 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
547 550
548 __ Bind(&wrong_num_arguments); 551 __ Bind(&wrong_num_arguments);
552 if (locals_space_size() != 0) {
553 // We need to unwind the space we reserved for locals/copied parms etc.
regis 2012/05/14 17:33:10 I add a comment here when reviewing your other ove
siva 2012/05/15 23:52:39 Yes, I incorporated your comment into the other CL
554 // as the NoSuchMethodFunction stub does not expect to see that area on
555 // the stack.
556 __ addl(ESP, Immediate(locals_space_size()));
557 }
549 if (function.IsClosureFunction()) { 558 if (function.IsClosureFunction()) {
550 GenerateCallRuntime(AstNode::kNoId, 559 GenerateCallRuntime(AstNode::kNoId,
551 0, 560 0,
552 kClosureArgumentMismatchRuntimeEntry); 561 kClosureArgumentMismatchRuntimeEntry);
553 } else { 562 } else {
554 // Invoke noSuchMethod function. 563 // Invoke noSuchMethod function.
555 const int kNumArgsChecked = 1; 564 const int kNumArgsChecked = 1;
556 ICData& ic_data = ICData::ZoneHandle(); 565 ICData& ic_data = ICData::ZoneHandle();
557 ic_data = ICData::New(parsed_function().function(), 566 ic_data = ICData::New(parsed_function().function(),
558 String::Handle(function.name()), 567 String::Handle(function.name()),
559 AstNode::kNoId, 568 AstNode::kNoId,
560 kNumArgsChecked); 569 kNumArgsChecked);
561 __ LoadObject(ECX, ic_data); 570 __ LoadObject(ECX, ic_data);
571 // EBP - 4 : PC marker, allows easy identification of RawInstruction obj.
562 // EBP : points to previous frame pointer. 572 // EBP : points to previous frame pointer.
563 // EBP + 4 : points to return address. 573 // EBP + 4 : points to return address.
564 // EBP + 8 : address of last argument (arg n-1). 574 // EBP + 8 : address of last argument (arg n-1).
565 // ESP + 8 + 4*(n-1) : address of first argument (arg 0). 575 // ESP + 8 + 4*(n-1) : address of first argument (arg 0).
566 // ECX : ic-data. 576 // ECX : ic-data.
567 // EDX : arguments descriptor array. 577 // EDX : arguments descriptor array.
568 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); 578 __ call(&StubCode::CallNoSuchMethodFunctionLabel());
569 } 579 }
570 580
571 if (FLAG_trace_functions) { 581 if (FLAG_trace_functions) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 if (parsed_function_.saved_context_var() != NULL) { 643 if (parsed_function_.saved_context_var() != NULL) {
634 // CTX on entry was saved, but not linked as context parent. 644 // CTX on entry was saved, but not linked as context parent.
635 GenerateLoadVariable(CTX, *parsed_function_.saved_context_var()); 645 GenerateLoadVariable(CTX, *parsed_function_.saved_context_var());
636 } else { 646 } else {
637 while (current_context_level-- > 0) { 647 while (current_context_level-- > 0) {
638 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); 648 __ movl(CTX, FieldAddress(CTX, Context::parent_offset()));
639 } 649 }
640 } 650 }
641 #ifdef DEBUG 651 #ifdef DEBUG
642 // Check that the entry stack size matches the exit stack size. 652 // Check that the entry stack size matches the exit stack size.
643 __ movl(EDX, EBP); 653 __ leal(EDX, Address(EBP, kLocalsOffsetFromFP));
644 __ subl(EDX, ESP); 654 __ subl(EDX, ESP);
645 ASSERT(locals_space_size() >= 0); 655 ASSERT(locals_space_size() >= 0);
646 __ cmpl(EDX, Immediate(locals_space_size())); 656 __ cmpl(EDX, Immediate(locals_space_size()));
647 Label wrong_stack; 657 Label wrong_stack;
648 __ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump); 658 __ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump);
649 #endif // DEBUG. 659 #endif // DEBUG.
650 660
651 if (!IsOptimizing()) { 661 if (!IsOptimizing()) {
652 // Count only in unoptimized code. 662 // Count only in unoptimized code.
653 // TODO(srdjan): Replace the counting code with a type feedback 663 // TODO(srdjan): Replace the counting code with a type feedback
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
868 set_context_level(scope->context_level()); 878 set_context_level(scope->context_level());
869 879
870 // If this node_sequence is the body of the function being compiled, copy 880 // If this node_sequence is the body of the function being compiled, copy
871 // the captured parameters from the frame into the context. 881 // the captured parameters from the frame into the context.
872 if (node_sequence == parsed_function_.node_sequence()) { 882 if (node_sequence == parsed_function_.node_sequence()) {
873 ASSERT(scope->context_level() == 1); 883 ASSERT(scope->context_level() == 1);
874 const Immediate raw_null = 884 const Immediate raw_null =
875 Immediate(reinterpret_cast<intptr_t>(Object::null())); 885 Immediate(reinterpret_cast<intptr_t>(Object::null()));
876 const Function& function = parsed_function_.function(); 886 const Function& function = parsed_function_.function();
877 const int num_params = function.NumberOfParameters(); 887 const int num_params = function.NumberOfParameters();
878 int param_frame_index = 888 int param_frame_index = (num_params == function.num_fixed_parameters()) ?
879 (num_params == function.num_fixed_parameters()) ? 1 + num_params : -1; 889 (1 + num_params) : ParsedFunction::kFirstStackSlotIndex;
880 for (int pos = 0; pos < num_params; param_frame_index--, pos++) { 890 for (int pos = 0; pos < num_params; param_frame_index--, pos++) {
881 LocalVariable* parameter = scope->VariableAt(pos); 891 LocalVariable* parameter = scope->VariableAt(pos);
882 ASSERT(parameter->owner() == scope); 892 ASSERT(parameter->owner() == scope);
883 if (parameter->is_captured()) { 893 if (parameter->is_captured()) {
884 // Copy parameter from local frame to current context. 894 // Copy parameter from local frame to current context.
885 const Address local_addr(EBP, param_frame_index * kWordSize); 895 const Address local_addr(EBP, param_frame_index * kWordSize);
886 __ movl(EAX, local_addr); 896 __ movl(EAX, local_addr);
887 GenerateStoreVariable(*parameter, EAX, EDX); 897 GenerateStoreVariable(*parameter, EAX, EDX);
888 // Write NULL to the source location to detect buggy accesses and 898 // Write NULL to the source location to detect buggy accesses and
889 // allow GC of passed value if it gets overwritten by a new value in 899 // allow GC of passed value if it gets overwritten by a new value in
(...skipping 1890 matching lines...) Expand 10 before | Expand all | Expand 10 after
2780 } 2790 }
2781 2791
2782 2792
2783 void CodeGenerator::VisitNativeBodyNode(NativeBodyNode* node) { 2793 void CodeGenerator::VisitNativeBodyNode(NativeBodyNode* node) {
2784 // Push the result place holder initialized to NULL. 2794 // Push the result place holder initialized to NULL.
2785 __ PushObject(Object::ZoneHandle()); 2795 __ PushObject(Object::ZoneHandle());
2786 // Pass a pointer to the first argument in EAX. 2796 // Pass a pointer to the first argument in EAX.
2787 if (!node->has_optional_parameters()) { 2797 if (!node->has_optional_parameters()) {
2788 __ leal(EAX, Address(EBP, (1 + node->argument_count()) * kWordSize)); 2798 __ leal(EAX, Address(EBP, (1 + node->argument_count()) * kWordSize));
2789 } else { 2799 } else {
2790 __ leal(EAX, Address(EBP, -1 * kWordSize)); 2800 __ leal(EAX,
2801 Address(EBP, ParsedFunction::kFirstStackSlotIndex * kWordSize));
2791 } 2802 }
2792 __ movl(ECX, Immediate(reinterpret_cast<uword>(node->native_c_function()))); 2803 __ movl(ECX, Immediate(reinterpret_cast<uword>(node->native_c_function())));
2793 __ movl(EDX, Immediate(node->argument_count())); 2804 __ movl(EDX, Immediate(node->argument_count()));
2794 GenerateCall(node->token_index(), 2805 GenerateCall(node->token_index(),
2795 &StubCode::CallNativeCFunctionLabel(), 2806 &StubCode::CallNativeCFunctionLabel(),
2796 PcDescriptors::kOther); 2807 PcDescriptors::kOther);
2797 // Result is on the stack. 2808 // Result is on the stack.
2798 if (!IsResultNeeded(node)) { 2809 if (!IsResultNeeded(node)) {
2799 __ popl(EAX); 2810 __ popl(EAX);
2800 } 2811 }
2801 } 2812 }
2802 2813
2803 2814
2804 void CodeGenerator::VisitCatchClauseNode(CatchClauseNode* node) { 2815 void CodeGenerator::VisitCatchClauseNode(CatchClauseNode* node) {
2805 // NOTE: The implicit variables ':saved_context', ':exception_var' 2816 // NOTE: The implicit variables ':saved_context', ':exception_var'
2806 // and ':stacktrace_var' can never be captured variables. 2817 // and ':stacktrace_var' can never be captured variables.
2807 // Restore CTX from local variable ':saved_context'. 2818 // Restore CTX from local variable ':saved_context'.
2808 GenerateLoadVariable(CTX, node->context_var()); 2819 GenerateLoadVariable(CTX, node->context_var());
2809 2820
2810 // Restore ESP from EBP as we are coming from a throw and the code for 2821 // Restore ESP from EBP as we are coming from a throw and the code for
2811 // popping arguments has not been run. 2822 // popping arguments has not been run.
2812 ASSERT(locals_space_size() >= 0); 2823 ASSERT(locals_space_size() >= 0);
2813 if (locals_space_size() == 0) { 2824 intptr_t offset_size = -locals_space_size() + kLocalsOffsetFromFP;
2814 __ movl(ESP, EBP); 2825 __ leal(ESP, Address(EBP, offset_size));
2815 } else {
2816 __ leal(ESP, Address(EBP, -locals_space_size()));
2817 }
2818 2826
2819 // The JumpToExceptionHandler trampoline code sets up 2827 // The JumpToExceptionHandler trampoline code sets up
2820 // - the exception object in EAX (kExceptionObjectReg) 2828 // - the exception object in EAX (kExceptionObjectReg)
2821 // - the stacktrace object in register EDX (kStackTraceObjectReg) 2829 // - the stacktrace object in register EDX (kStackTraceObjectReg)
2822 // We now setup the exception object and the trace object 2830 // We now setup the exception object and the trace object
2823 // so that the handler code has access to these objects. 2831 // so that the handler code has access to these objects.
2824 GenerateStoreVariable(node->exception_var(), 2832 GenerateStoreVariable(node->exception_var(),
2825 kExceptionObjectReg, 2833 kExceptionObjectReg,
2826 kNoRegister); 2834 kNoRegister);
2827 GenerateStoreVariable(node->stacktrace_var(), 2835 GenerateStoreVariable(node->stacktrace_var(),
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
2959 const Error& error = Error::Handle( 2967 const Error& error = Error::Handle(
2960 Parser::FormatError(script, token_index, "Error", format, args)); 2968 Parser::FormatError(script, token_index, "Error", format, args));
2961 va_end(args); 2969 va_end(args);
2962 Isolate::Current()->long_jump_base()->Jump(1, error); 2970 Isolate::Current()->long_jump_base()->Jump(1, error);
2963 UNREACHABLE(); 2971 UNREACHABLE();
2964 } 2972 }
2965 2973
2966 } // namespace dart 2974 } // namespace dart
2967 2975
2968 #endif // defined TARGET_ARCH_IA32 2976 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698