Chromium Code Reviews| 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/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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |