| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #include "codegen.h" | 7 #include "codegen.h" |
| 8 #include "compiler.h" | 8 #include "compiler.h" |
| 9 #include "debug.h" | 9 #include "debug.h" |
| 10 #include "full-codegen.h" | 10 #include "full-codegen.h" |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) { | 374 void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) { |
| 375 // Fill in the deoptimization information. | 375 // Fill in the deoptimization information. |
| 376 ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty()); | 376 ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty()); |
| 377 if (!info_->HasDeoptimizationSupport()) return; | 377 if (!info_->HasDeoptimizationSupport()) return; |
| 378 int length = bailout_entries_.length(); | 378 int length = bailout_entries_.length(); |
| 379 Handle<DeoptimizationOutputData> data = | 379 Handle<DeoptimizationOutputData> data = |
| 380 DeoptimizationOutputData::New(isolate(), length, TENURED); | 380 DeoptimizationOutputData::New(isolate(), length, TENURED); |
| 381 for (int i = 0; i < length; i++) { | 381 for (int i = 0; i < length; i++) { |
| 382 data->SetAstId(i, bailout_entries_[i].id); | 382 data->SetAstId(i, bailout_entries_[i].id); |
| 383 data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state)); | 383 data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state)); |
| 384 #if defined(COMPARE_OPT_STACK_HEIGHT) |
| 385 data->SetStackHeight(i, Smi::FromInt(bailout_entries_[i].stack_height)); |
| 386 #endif |
| 384 } | 387 } |
| 385 code->set_deoptimization_data(*data); | 388 code->set_deoptimization_data(*data); |
| 386 } | 389 } |
| 387 | 390 |
| 388 | 391 |
| 389 void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) { | 392 void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) { |
| 390 Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo(); | 393 Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo(); |
| 391 info->set_ic_total_count(ic_total_count_); | 394 info->set_ic_total_count(ic_total_count_); |
| 392 ASSERT(!isolate()->heap()->InNewSpace(*info)); | 395 ASSERT(!isolate()->heap()->InNewSpace(*info)); |
| 393 code->set_type_feedback_info(*info); | 396 code->set_type_feedback_info(*info); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 // was called. | 444 // was called. |
| 442 ASSERT(!call->return_is_recorded_); | 445 ASSERT(!call->return_is_recorded_); |
| 443 call->return_is_recorded_ = true; | 446 call->return_is_recorded_ = true; |
| 444 #endif | 447 #endif |
| 445 } | 448 } |
| 446 | 449 |
| 447 | 450 |
| 448 void FullCodeGenerator::PrepareForBailoutForId(BailoutId id, State state) { | 451 void FullCodeGenerator::PrepareForBailoutForId(BailoutId id, State state) { |
| 449 // There's no need to prepare this code for bailouts from already optimized | 452 // There's no need to prepare this code for bailouts from already optimized |
| 450 // code or code that can't be optimized. | 453 // code or code that can't be optimized. |
| 451 if (!info_->HasDeoptimizationSupport()) return; | 454 if (!info_->HasDeoptimizationSupport()) { |
| 455 // We still need to insert the check to make sure that we generate exactly |
| 456 // the same code |
| 457 CheckStackHeight(); |
| 458 return; |
| 459 } |
| 452 unsigned pc_and_state = | 460 unsigned pc_and_state = |
| 453 StateField::encode(state) | PcField::encode(masm_->pc_offset()); | 461 StateField::encode(state) | PcField::encode(masm_->pc_offset()); |
| 454 ASSERT(Smi::IsValid(pc_and_state)); | 462 ASSERT(Smi::IsValid(pc_and_state)); |
| 455 #ifdef DEBUG | 463 #ifdef DEBUG |
| 456 for (int i = 0; i < bailout_entries_.length(); ++i) { | 464 for (int i = 0; i < bailout_entries_.length(); ++i) { |
| 457 ASSERT(bailout_entries_[i].id != id); | 465 ASSERT(bailout_entries_[i].id != id); |
| 458 } | 466 } |
| 459 #endif | 467 #endif |
| 460 BailoutEntry entry = { id, pc_and_state }; | 468 // If the we store the top of the stack register, pretend it is on the stack |
| 469 int stack_height = stack_height_.get() + (state == TOS_REG ? 1 : 0); |
| 470 BailoutEntry entry = { id, pc_and_state, stack_height }; |
| 461 bailout_entries_.Add(entry, zone()); | 471 bailout_entries_.Add(entry, zone()); |
| 472 CheckStackHeight(); |
| 462 } | 473 } |
| 463 | 474 |
| 464 | 475 |
| 465 void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) { | 476 void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) { |
| 466 // The pc offset does not need to be encoded and packed together with a state. | 477 // The pc offset does not need to be encoded and packed together with a state. |
| 467 ASSERT(masm_->pc_offset() > 0); | 478 ASSERT(masm_->pc_offset() > 0); |
| 468 ASSERT(loop_depth() > 0); | 479 ASSERT(loop_depth() > 0); |
| 469 uint8_t depth = Min(loop_depth(), Code::kMaxLoopNestingMarker); | 480 uint8_t depth = Min(loop_depth(), Code::kMaxLoopNestingMarker); |
| 470 BackEdgeEntry entry = | 481 BackEdgeEntry entry = |
| 471 { ast_id, static_cast<unsigned>(masm_->pc_offset()), depth }; | 482 { ast_id, static_cast<unsigned>(masm_->pc_offset()), depth }; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 485 void FullCodeGenerator::EffectContext::Plug(Register reg) const { | 496 void FullCodeGenerator::EffectContext::Plug(Register reg) const { |
| 486 } | 497 } |
| 487 | 498 |
| 488 | 499 |
| 489 void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const { | 500 void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const { |
| 490 __ Move(result_register(), reg); | 501 __ Move(result_register(), reg); |
| 491 } | 502 } |
| 492 | 503 |
| 493 | 504 |
| 494 void FullCodeGenerator::StackValueContext::Plug(Register reg) const { | 505 void FullCodeGenerator::StackValueContext::Plug(Register reg) const { |
| 495 __ Push(reg); | 506 codegen()->AsmPush(reg); |
| 496 } | 507 } |
| 497 | 508 |
| 498 | 509 |
| 499 void FullCodeGenerator::TestContext::Plug(Register reg) const { | 510 void FullCodeGenerator::TestContext::Plug(Register reg) const { |
| 500 // For simplicity we always test the accumulator register. | 511 // For simplicity we always test the accumulator register. |
| 501 __ Move(result_register(), reg); | 512 __ Move(result_register(), reg); |
| 502 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 513 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
| 503 codegen()->DoTest(this); | 514 codegen()->DoTest(this); |
| 504 } | 515 } |
| 505 | 516 |
| 506 | 517 |
| 507 void FullCodeGenerator::EffectContext::PlugTOS() const { | 518 void FullCodeGenerator::EffectContext::PlugTOS() const { |
| 508 __ Drop(1); | 519 codegen()->AsmDrop(1); |
| 509 } | 520 } |
| 510 | 521 |
| 511 | 522 |
| 512 void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const { | 523 void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const { |
| 513 __ Pop(result_register()); | 524 codegen()->AsmPop(result_register()); |
| 514 } | 525 } |
| 515 | 526 |
| 516 | 527 |
| 517 void FullCodeGenerator::StackValueContext::PlugTOS() const { | 528 void FullCodeGenerator::StackValueContext::PlugTOS() const { |
| 518 } | 529 } |
| 519 | 530 |
| 520 | 531 |
| 521 void FullCodeGenerator::TestContext::PlugTOS() const { | 532 void FullCodeGenerator::TestContext::PlugTOS() const { |
| 522 // For simplicity we always test the accumulator register. | 533 // For simplicity we always test the accumulator register. |
| 523 __ Pop(result_register()); | 534 codegen()->AsmPop(result_register()); |
| 524 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 535 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
| 525 codegen()->DoTest(this); | 536 codegen()->DoTest(this); |
| 526 } | 537 } |
| 527 | 538 |
| 528 | 539 |
| 529 void FullCodeGenerator::EffectContext::PrepareTest( | 540 void FullCodeGenerator::EffectContext::PrepareTest( |
| 530 Label* materialize_true, | 541 Label* materialize_true, |
| 531 Label* materialize_false, | 542 Label* materialize_false, |
| 532 Label** if_true, | 543 Label** if_true, |
| 533 Label** if_false, | 544 Label** if_false, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 if (module != NULL) { | 601 if (module != NULL) { |
| 591 Comment cmnt(masm_, "[ Link nested modules"); | 602 Comment cmnt(masm_, "[ Link nested modules"); |
| 592 Scope* scope = module->body()->scope(); | 603 Scope* scope = module->body()->scope(); |
| 593 Interface* interface = scope->interface(); | 604 Interface* interface = scope->interface(); |
| 594 ASSERT(interface->IsModule() && interface->IsFrozen()); | 605 ASSERT(interface->IsModule() && interface->IsFrozen()); |
| 595 | 606 |
| 596 interface->Allocate(scope->module_var()->index()); | 607 interface->Allocate(scope->module_var()->index()); |
| 597 | 608 |
| 598 // Set up module context. | 609 // Set up module context. |
| 599 ASSERT(scope->interface()->Index() >= 0); | 610 ASSERT(scope->interface()->Index() >= 0); |
| 600 __ Push(Smi::FromInt(scope->interface()->Index())); | 611 AsmPushSmi(Smi::FromInt(scope->interface()->Index())); |
| 601 __ Push(scope->GetScopeInfo()); | 612 AsmPushHandle(scope->GetScopeInfo()); |
| 602 __ CallRuntime(Runtime::kHiddenPushModuleContext, 2); | 613 AsmCallRuntime(Runtime::kHiddenPushModuleContext, 2); |
| 603 StoreToFrameField(StandardFrameConstants::kContextOffset, | 614 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 604 context_register()); | 615 context_register()); |
| 605 | 616 |
| 606 AllocateModules(scope->declarations()); | 617 AllocateModules(scope->declarations()); |
| 607 | 618 |
| 608 // Pop module context. | 619 // Pop module context. |
| 609 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 620 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 610 // Update local stack frame context field. | 621 // Update local stack frame context field. |
| 611 StoreToFrameField(StandardFrameConstants::kContextOffset, | 622 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 612 context_register()); | 623 context_register()); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 681 Handle<FixedArray> saved_modules = modules_; | 692 Handle<FixedArray> saved_modules = modules_; |
| 682 int saved_module_index = module_index_; | 693 int saved_module_index = module_index_; |
| 683 ZoneList<Handle<Object> >* saved_globals = globals_; | 694 ZoneList<Handle<Object> >* saved_globals = globals_; |
| 684 ZoneList<Handle<Object> > inner_globals(10, zone()); | 695 ZoneList<Handle<Object> > inner_globals(10, zone()); |
| 685 globals_ = &inner_globals; | 696 globals_ = &inner_globals; |
| 686 | 697 |
| 687 if (scope_->num_modules() != 0) { | 698 if (scope_->num_modules() != 0) { |
| 688 // This is a scope hosting modules. Allocate a descriptor array to pass | 699 // This is a scope hosting modules. Allocate a descriptor array to pass |
| 689 // to the runtime for initialization. | 700 // to the runtime for initialization. |
| 690 Comment cmnt(masm_, "[ Allocate modules"); | 701 Comment cmnt(masm_, "[ Allocate modules"); |
| 702 |
| 691 ASSERT(scope_->is_global_scope()); | 703 ASSERT(scope_->is_global_scope()); |
| 692 modules_ = | 704 modules_ = |
| 693 isolate()->factory()->NewFixedArray(scope_->num_modules(), TENURED); | 705 isolate()->factory()->NewFixedArray(scope_->num_modules(), TENURED); |
| 694 module_index_ = 0; | 706 module_index_ = 0; |
| 695 | 707 |
| 696 // Generate code for allocating all modules, including nested ones. | 708 // Generate code for allocating all modules, including nested ones. |
| 697 // The allocated contexts are stored in internal variables in this scope. | 709 // The allocated contexts are stored in internal variables in this scope. |
| 698 AllocateModules(declarations); | 710 AllocateModules(declarations); |
| 699 } | 711 } |
| 700 | 712 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 730 | 742 |
| 731 Comment cmnt(masm_, "[ ModuleLiteral"); | 743 Comment cmnt(masm_, "[ ModuleLiteral"); |
| 732 SetStatementPosition(block); | 744 SetStatementPosition(block); |
| 733 | 745 |
| 734 ASSERT(!modules_.is_null()); | 746 ASSERT(!modules_.is_null()); |
| 735 ASSERT(module_index_ < modules_->length()); | 747 ASSERT(module_index_ < modules_->length()); |
| 736 int index = module_index_++; | 748 int index = module_index_++; |
| 737 | 749 |
| 738 // Set up module context. | 750 // Set up module context. |
| 739 ASSERT(interface->Index() >= 0); | 751 ASSERT(interface->Index() >= 0); |
| 740 __ Push(Smi::FromInt(interface->Index())); | 752 AsmPushSmi(Smi::FromInt(interface->Index())); |
| 741 __ Push(Smi::FromInt(0)); | 753 AsmPushSmi(Smi::FromInt(0)); |
| 742 __ CallRuntime(Runtime::kHiddenPushModuleContext, 2); | 754 AsmCallRuntime(Runtime::kHiddenPushModuleContext, 2); |
| 743 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 755 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
| 744 | 756 |
| 745 { | 757 { |
| 746 Comment cmnt(masm_, "[ Declarations"); | 758 Comment cmnt(masm_, "[ Declarations"); |
| 747 VisitDeclarations(scope_->declarations()); | 759 VisitDeclarations(scope_->declarations()); |
| 748 } | 760 } |
| 749 | 761 |
| 750 // Populate the module description. | 762 // Populate the module description. |
| 751 Handle<ModuleInfo> description = | 763 Handle<ModuleInfo> description = |
| 752 ModuleInfo::Create(isolate(), interface, scope_); | 764 ModuleInfo::Create(isolate(), interface, scope_); |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 963 Label done; | 975 Label done; |
| 964 | 976 |
| 965 if (context()->IsTest()) { | 977 if (context()->IsTest()) { |
| 966 Label eval_right; | 978 Label eval_right; |
| 967 const TestContext* test = TestContext::cast(context()); | 979 const TestContext* test = TestContext::cast(context()); |
| 968 if (is_logical_and) { | 980 if (is_logical_and) { |
| 969 VisitForControl(left, &eval_right, test->false_label(), &eval_right); | 981 VisitForControl(left, &eval_right, test->false_label(), &eval_right); |
| 970 } else { | 982 } else { |
| 971 VisitForControl(left, test->true_label(), &eval_right, &eval_right); | 983 VisitForControl(left, test->true_label(), &eval_right, &eval_right); |
| 972 } | 984 } |
| 985 __ bind(&eval_right); |
| 973 PrepareForBailoutForId(right_id, NO_REGISTERS); | 986 PrepareForBailoutForId(right_id, NO_REGISTERS); |
| 974 __ bind(&eval_right); | |
| 975 | |
| 976 } else if (context()->IsAccumulatorValue()) { | 987 } else if (context()->IsAccumulatorValue()) { |
| 977 VisitForAccumulatorValue(left); | 988 VisitForAccumulatorValue(left); |
| 978 // We want the value in the accumulator for the test, and on the stack in | 989 // We want the value in the accumulator for the test, and on the stack in |
| 979 // case we need it. | 990 // case we need it. |
| 980 __ Push(result_register()); | 991 AsmPush(result_register()); |
| 981 Label discard, restore; | 992 Label discard, restore; |
| 982 if (is_logical_and) { | 993 if (is_logical_and) { |
| 983 DoTest(left, &discard, &restore, &restore); | 994 DoTest(left, &discard, &restore, &restore); |
| 984 } else { | 995 } else { |
| 985 DoTest(left, &restore, &discard, &restore); | 996 DoTest(left, &restore, &discard, &restore); |
| 986 } | 997 } |
| 998 StackHeightWrapper branch_stack_height = CurrentStackHeight(); |
| 987 __ bind(&restore); | 999 __ bind(&restore); |
| 988 __ Pop(result_register()); | 1000 AsmPop(result_register()); |
| 989 __ jmp(&done); | 1001 __ jmp(&done); |
| 990 __ bind(&discard); | 1002 __ bind(&discard); |
| 991 __ Drop(1); | 1003 SetStackHeight(branch_stack_height); |
| 1004 AsmDrop(1); |
| 992 PrepareForBailoutForId(right_id, NO_REGISTERS); | 1005 PrepareForBailoutForId(right_id, NO_REGISTERS); |
| 993 | |
| 994 } else if (context()->IsStackValue()) { | 1006 } else if (context()->IsStackValue()) { |
| 995 VisitForAccumulatorValue(left); | 1007 VisitForAccumulatorValue(left); |
| 996 // We want the value in the accumulator for the test, and on the stack in | 1008 // We want the value in the accumulator for the test, and on the stack in |
| 997 // case we need it. | 1009 // case we need it. |
| 998 __ Push(result_register()); | 1010 AsmPush(result_register()); |
| 999 Label discard; | 1011 Label discard; |
| 1000 if (is_logical_and) { | 1012 if (is_logical_and) { |
| 1001 DoTest(left, &discard, &done, &discard); | 1013 DoTest(left, &discard, &done, &discard); |
| 1002 } else { | 1014 } else { |
| 1003 DoTest(left, &done, &discard, &discard); | 1015 DoTest(left, &done, &discard, &discard); |
| 1004 } | 1016 } |
| 1005 __ bind(&discard); | 1017 __ bind(&discard); |
| 1006 __ Drop(1); | 1018 AsmDrop(1); |
| 1007 PrepareForBailoutForId(right_id, NO_REGISTERS); | 1019 PrepareForBailoutForId(right_id, NO_REGISTERS); |
| 1008 | |
| 1009 } else { | 1020 } else { |
| 1010 ASSERT(context()->IsEffect()); | 1021 ASSERT(context()->IsEffect()); |
| 1011 Label eval_right; | 1022 Label eval_right; |
| 1012 if (is_logical_and) { | 1023 if (is_logical_and) { |
| 1013 VisitForControl(left, &eval_right, &done, &eval_right); | 1024 VisitForControl(left, &eval_right, &done, &eval_right); |
| 1014 } else { | 1025 } else { |
| 1015 VisitForControl(left, &done, &eval_right, &eval_right); | 1026 VisitForControl(left, &done, &eval_right, &eval_right); |
| 1016 } | 1027 } |
| 1028 __ bind(&eval_right); |
| 1017 PrepareForBailoutForId(right_id, NO_REGISTERS); | 1029 PrepareForBailoutForId(right_id, NO_REGISTERS); |
| 1018 __ bind(&eval_right); | |
| 1019 } | 1030 } |
| 1020 | 1031 |
| 1021 VisitInDuplicateContext(right); | 1032 VisitInDuplicateContext(right); |
| 1022 __ bind(&done); | 1033 __ bind(&done); |
| 1023 } | 1034 } |
| 1024 | 1035 |
| 1025 | 1036 |
| 1026 void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { | 1037 void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { |
| 1027 Token::Value op = expr->op(); | 1038 Token::Value op = expr->op(); |
| 1028 Comment cmnt(masm_, "[ ArithmeticExpression"); | 1039 Comment cmnt(masm_, "[ ArithmeticExpression"); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1049 Comment cmnt(masm_, "[ Block"); | 1060 Comment cmnt(masm_, "[ Block"); |
| 1050 NestedBlock nested_block(this, stmt); | 1061 NestedBlock nested_block(this, stmt); |
| 1051 SetStatementPosition(stmt); | 1062 SetStatementPosition(stmt); |
| 1052 | 1063 |
| 1053 Scope* saved_scope = scope(); | 1064 Scope* saved_scope = scope(); |
| 1054 // Push a block context when entering a block with block scoped variables. | 1065 // Push a block context when entering a block with block scoped variables. |
| 1055 if (stmt->scope() != NULL) { | 1066 if (stmt->scope() != NULL) { |
| 1056 scope_ = stmt->scope(); | 1067 scope_ = stmt->scope(); |
| 1057 ASSERT(!scope_->is_module_scope()); | 1068 ASSERT(!scope_->is_module_scope()); |
| 1058 { Comment cmnt(masm_, "[ Extend block context"); | 1069 { Comment cmnt(masm_, "[ Extend block context"); |
| 1059 __ Push(scope_->GetScopeInfo()); | 1070 AsmPushHandle(scope_->GetScopeInfo()); |
| 1060 PushFunctionArgumentForContextAllocation(); | 1071 PushFunctionArgumentForContextAllocation(); |
| 1061 __ CallRuntime(Runtime::kHiddenPushBlockContext, 2); | 1072 AsmCallRuntime(Runtime::kHiddenPushBlockContext, 2); |
| 1062 | 1073 |
| 1063 // Replace the context stored in the frame. | 1074 // Replace the context stored in the frame. |
| 1064 StoreToFrameField(StandardFrameConstants::kContextOffset, | 1075 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 1065 context_register()); | 1076 context_register()); |
| 1066 } | 1077 } |
| 1067 { Comment cmnt(masm_, "[ Declarations"); | 1078 { Comment cmnt(masm_, "[ Declarations"); |
| 1068 VisitDeclarations(scope_->declarations()); | 1079 VisitDeclarations(scope_->declarations()); |
| 1069 } | 1080 } |
| 1070 } | 1081 } |
| 1071 | 1082 |
| 1072 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 1083 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
| 1073 VisitStatements(stmt->statements()); | 1084 VisitStatements(stmt->statements()); |
| 1074 scope_ = saved_scope; | 1085 scope_ = saved_scope; |
| 1075 __ bind(nested_block.break_label()); | 1086 __ bind(nested_block.break_label()); |
| 1076 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 1087 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 1077 | 1088 |
| 1078 // Pop block context if necessary. | 1089 // Pop block context if necessary. |
| 1079 if (stmt->scope() != NULL) { | 1090 if (stmt->scope() != NULL) { |
| 1080 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 1091 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 1081 // Update local stack frame context field. | 1092 // Update local stack frame context field. |
| 1082 StoreToFrameField(StandardFrameConstants::kContextOffset, | 1093 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 1083 context_register()); | 1094 context_register()); |
| 1084 } | 1095 } |
| 1085 } | 1096 } |
| 1086 | 1097 |
| 1087 | 1098 |
| 1088 void FullCodeGenerator::VisitModuleStatement(ModuleStatement* stmt) { | 1099 void FullCodeGenerator::VisitModuleStatement(ModuleStatement* stmt) { |
| 1089 Comment cmnt(masm_, "[ Module context"); | 1100 Comment cmnt(masm_, "[ Module context"); |
| 1090 | 1101 |
| 1091 __ Push(Smi::FromInt(stmt->proxy()->interface()->Index())); | 1102 AsmPushSmi(Smi::FromInt(stmt->proxy()->interface()->Index())); |
| 1092 __ Push(Smi::FromInt(0)); | 1103 AsmPushSmi(Smi::FromInt(0)); |
| 1093 __ CallRuntime(Runtime::kHiddenPushModuleContext, 2); | 1104 AsmCallRuntime(Runtime::kHiddenPushModuleContext, 2); |
| 1094 StoreToFrameField( | 1105 StoreToFrameField( |
| 1095 StandardFrameConstants::kContextOffset, context_register()); | 1106 StandardFrameConstants::kContextOffset, context_register()); |
| 1096 | 1107 |
| 1097 Scope* saved_scope = scope_; | 1108 Scope* saved_scope = scope_; |
| 1098 scope_ = stmt->body()->scope(); | 1109 scope_ = stmt->body()->scope(); |
| 1099 VisitStatements(stmt->body()->statements()); | 1110 VisitStatements(stmt->body()->statements()); |
| 1100 scope_ = saved_scope; | 1111 scope_ = saved_scope; |
| 1101 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 1112 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 1102 // Update local stack frame context field. | 1113 // Update local stack frame context field. |
| 1103 StoreToFrameField(StandardFrameConstants::kContextOffset, | 1114 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1118 } | 1129 } |
| 1119 | 1130 |
| 1120 | 1131 |
| 1121 void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) { | 1132 void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) { |
| 1122 Comment cmnt(masm_, "[ IfStatement"); | 1133 Comment cmnt(masm_, "[ IfStatement"); |
| 1123 SetStatementPosition(stmt); | 1134 SetStatementPosition(stmt); |
| 1124 Label then_part, else_part, done; | 1135 Label then_part, else_part, done; |
| 1125 | 1136 |
| 1126 if (stmt->HasElseStatement()) { | 1137 if (stmt->HasElseStatement()) { |
| 1127 VisitForControl(stmt->condition(), &then_part, &else_part, &then_part); | 1138 VisitForControl(stmt->condition(), &then_part, &else_part, &then_part); |
| 1139 StackHeightWrapper if_stack_height = CurrentStackHeight(); |
| 1140 __ bind(&then_part); |
| 1128 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS); | 1141 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS); |
| 1129 __ bind(&then_part); | |
| 1130 Visit(stmt->then_statement()); | 1142 Visit(stmt->then_statement()); |
| 1131 __ jmp(&done); | 1143 __ jmp(&done); |
| 1132 | 1144 |
| 1145 __ bind(&else_part); |
| 1146 SetStackHeight(if_stack_height); |
| 1133 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS); | 1147 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS); |
| 1134 __ bind(&else_part); | |
| 1135 Visit(stmt->else_statement()); | 1148 Visit(stmt->else_statement()); |
| 1136 } else { | 1149 } else { |
| 1137 VisitForControl(stmt->condition(), &then_part, &done, &then_part); | 1150 VisitForControl(stmt->condition(), &then_part, &done, &then_part); |
| 1151 __ bind(&then_part); |
| 1138 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS); | 1152 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS); |
| 1139 __ bind(&then_part); | |
| 1140 Visit(stmt->then_statement()); | 1153 Visit(stmt->then_statement()); |
| 1141 | 1154 |
| 1142 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS); | 1155 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS); |
| 1143 } | 1156 } |
| 1144 __ bind(&done); | 1157 __ bind(&done); |
| 1145 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS); | 1158 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS); |
| 1146 } | 1159 } |
| 1147 | 1160 |
| 1148 | 1161 |
| 1149 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { | 1162 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { |
| 1150 Comment cmnt(masm_, "[ ContinueStatement"); | 1163 Comment cmnt(masm_, "[ ContinueStatement"); |
| 1151 SetStatementPosition(stmt); | 1164 SetStatementPosition(stmt); |
| 1152 NestedStatement* current = nesting_stack_; | 1165 NestedStatement* current = nesting_stack_; |
| 1166 StackHeightWrapper original_stack_height = CurrentStackHeight(); |
| 1153 int stack_depth = 0; | 1167 int stack_depth = 0; |
| 1154 int context_length = 0; | 1168 int context_length = 0; |
| 1155 // When continuing, we clobber the unpredictable value in the accumulator | 1169 // When continuing, we clobber the unpredictable value in the accumulator |
| 1156 // with one that's safe for GC. If we hit an exit from the try block of | 1170 // with one that's safe for GC. If we hit an exit from the try block of |
| 1157 // try...finally on our way out, we will unconditionally preserve the | 1171 // try...finally on our way out, we will unconditionally preserve the |
| 1158 // accumulator on the stack. | 1172 // accumulator on the stack. |
| 1159 ClearAccumulator(); | 1173 ClearAccumulator(); |
| 1160 while (!current->IsContinueTarget(stmt->target())) { | 1174 while (!current->IsContinueTarget(stmt->target())) { |
| 1161 current = current->Exit(&stack_depth, &context_length); | 1175 current = current->Exit(&stack_depth, &context_length); |
| 1162 } | 1176 } |
| 1163 __ Drop(stack_depth); | 1177 AsmDrop(stack_depth); |
| 1164 if (context_length > 0) { | 1178 if (context_length > 0) { |
| 1165 while (context_length > 0) { | 1179 while (context_length > 0) { |
| 1166 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 1180 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 1167 --context_length; | 1181 --context_length; |
| 1168 } | 1182 } |
| 1169 StoreToFrameField(StandardFrameConstants::kContextOffset, | 1183 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 1170 context_register()); | 1184 context_register()); |
| 1171 } | 1185 } |
| 1172 | 1186 |
| 1173 __ jmp(current->AsIteration()->continue_label()); | 1187 __ jmp(current->AsIteration()->continue_label()); |
| 1188 SetStackHeight(original_stack_height); |
| 1174 } | 1189 } |
| 1175 | 1190 |
| 1176 | 1191 |
| 1177 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 1192 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
| 1178 Comment cmnt(masm_, "[ BreakStatement"); | 1193 Comment cmnt(masm_, "[ BreakStatement"); |
| 1179 SetStatementPosition(stmt); | 1194 SetStatementPosition(stmt); |
| 1180 NestedStatement* current = nesting_stack_; | 1195 NestedStatement* current = nesting_stack_; |
| 1196 StackHeightWrapper original_stack_height = CurrentStackHeight(); |
| 1181 int stack_depth = 0; | 1197 int stack_depth = 0; |
| 1182 int context_length = 0; | 1198 int context_length = 0; |
| 1183 // When breaking, we clobber the unpredictable value in the accumulator | 1199 // When breaking, we clobber the unpredictable value in the accumulator |
| 1184 // with one that's safe for GC. If we hit an exit from the try block of | 1200 // with one that's safe for GC. If we hit an exit from the try block of |
| 1185 // try...finally on our way out, we will unconditionally preserve the | 1201 // try...finally on our way out, we will unconditionally preserve the |
| 1186 // accumulator on the stack. | 1202 // accumulator on the stack. |
| 1187 ClearAccumulator(); | 1203 ClearAccumulator(); |
| 1188 while (!current->IsBreakTarget(stmt->target())) { | 1204 while (!current->IsBreakTarget(stmt->target())) { |
| 1189 current = current->Exit(&stack_depth, &context_length); | 1205 current = current->Exit(&stack_depth, &context_length); |
| 1190 } | 1206 } |
| 1191 __ Drop(stack_depth); | 1207 AsmDrop(stack_depth); |
| 1192 if (context_length > 0) { | 1208 if (context_length > 0) { |
| 1193 while (context_length > 0) { | 1209 while (context_length > 0) { |
| 1194 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 1210 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 1195 --context_length; | 1211 --context_length; |
| 1196 } | 1212 } |
| 1197 StoreToFrameField(StandardFrameConstants::kContextOffset, | 1213 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 1198 context_register()); | 1214 context_register()); |
| 1199 } | 1215 } |
| 1200 | 1216 |
| 1201 __ jmp(current->AsBreakable()->break_label()); | 1217 __ jmp(current->AsBreakable()->break_label()); |
| 1218 SetStackHeight(original_stack_height); |
| 1202 } | 1219 } |
| 1203 | 1220 |
| 1204 | 1221 |
| 1205 void FullCodeGenerator::EmitUnwindBeforeReturn() { | 1222 void FullCodeGenerator::EmitUnwindBeforeReturn() { |
| 1206 NestedStatement* current = nesting_stack_; | 1223 NestedStatement* current = nesting_stack_; |
| 1207 int stack_depth = 0; | 1224 int stack_depth = 0; |
| 1208 int context_length = 0; | 1225 int context_length = 0; |
| 1209 while (current != NULL) { | 1226 while (current != NULL) { |
| 1210 current = current->Exit(&stack_depth, &context_length); | 1227 current = current->Exit(&stack_depth, &context_length); |
| 1211 } | 1228 } |
| 1212 __ Drop(stack_depth); | 1229 AsmDrop(stack_depth); |
| 1213 } | 1230 } |
| 1214 | 1231 |
| 1215 | 1232 |
| 1216 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 1233 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
| 1217 Comment cmnt(masm_, "[ ReturnStatement"); | 1234 Comment cmnt(masm_, "[ ReturnStatement"); |
| 1218 SetStatementPosition(stmt); | 1235 SetStatementPosition(stmt); |
| 1219 Expression* expr = stmt->expression(); | 1236 Expression* expr = stmt->expression(); |
| 1220 VisitForAccumulatorValue(expr); | 1237 VisitForAccumulatorValue(expr); |
| 1238 StackHeightWrapper previous_stack_height = CurrentStackHeight(); |
| 1221 EmitUnwindBeforeReturn(); | 1239 EmitUnwindBeforeReturn(); |
| 1222 EmitReturnSequence(); | 1240 EmitReturnSequence(); |
| 1241 // Reset the expected stack height |
| 1242 SetStackHeight(previous_stack_height); |
| 1223 } | 1243 } |
| 1224 | 1244 |
| 1225 | 1245 |
| 1226 void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) { | 1246 void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) { |
| 1227 Comment cmnt(masm_, "[ WithStatement"); | 1247 Comment cmnt(masm_, "[ WithStatement"); |
| 1228 SetStatementPosition(stmt); | 1248 SetStatementPosition(stmt); |
| 1229 | 1249 |
| 1230 VisitForStackValue(stmt->expression()); | 1250 VisitForStackValue(stmt->expression()); |
| 1231 PushFunctionArgumentForContextAllocation(); | 1251 PushFunctionArgumentForContextAllocation(); |
| 1232 __ CallRuntime(Runtime::kHiddenPushWithContext, 2); | 1252 AsmCallRuntime(Runtime::kHiddenPushWithContext, 2); |
| 1233 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 1253 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
| 1234 | 1254 |
| 1235 Scope* saved_scope = scope(); | 1255 Scope* saved_scope = scope(); |
| 1236 scope_ = stmt->scope(); | 1256 scope_ = stmt->scope(); |
| 1237 { WithOrCatch body(this); | 1257 { WithOrCatch body(this); |
| 1238 Visit(stmt->statement()); | 1258 Visit(stmt->statement()); |
| 1239 } | 1259 } |
| 1240 scope_ = saved_scope; | 1260 scope_ = saved_scope; |
| 1241 | 1261 |
| 1242 // Pop context. | 1262 // Pop context. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1261 // possible to break on the condition. | 1281 // possible to break on the condition. |
| 1262 __ bind(loop_statement.continue_label()); | 1282 __ bind(loop_statement.continue_label()); |
| 1263 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); | 1283 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); |
| 1264 SetExpressionPosition(stmt->cond()); | 1284 SetExpressionPosition(stmt->cond()); |
| 1265 VisitForControl(stmt->cond(), | 1285 VisitForControl(stmt->cond(), |
| 1266 &book_keeping, | 1286 &book_keeping, |
| 1267 loop_statement.break_label(), | 1287 loop_statement.break_label(), |
| 1268 &book_keeping); | 1288 &book_keeping); |
| 1269 | 1289 |
| 1270 // Check stack before looping. | 1290 // Check stack before looping. |
| 1291 __ bind(&book_keeping); |
| 1271 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); | 1292 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); |
| 1272 __ bind(&book_keeping); | |
| 1273 EmitBackEdgeBookkeeping(stmt, &body); | 1293 EmitBackEdgeBookkeeping(stmt, &body); |
| 1274 __ jmp(&body); | 1294 __ jmp(&body); |
| 1275 | 1295 |
| 1296 __ bind(loop_statement.break_label()); |
| 1276 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 1297 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 1277 __ bind(loop_statement.break_label()); | |
| 1278 decrement_loop_depth(); | 1298 decrement_loop_depth(); |
| 1279 } | 1299 } |
| 1280 | 1300 |
| 1281 | 1301 |
| 1282 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 1302 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
| 1283 Comment cmnt(masm_, "[ WhileStatement"); | 1303 Comment cmnt(masm_, "[ WhileStatement"); |
| 1284 Label test, body; | 1304 Label test, body; |
| 1285 | 1305 |
| 1286 Iteration loop_statement(this, stmt); | 1306 Iteration loop_statement(this, stmt); |
| 1287 increment_loop_depth(); | 1307 increment_loop_depth(); |
| 1288 | 1308 |
| 1289 // Emit the test at the bottom of the loop. | 1309 // Emit the test at the bottom of the loop. |
| 1290 __ jmp(&test); | 1310 __ jmp(&test); |
| 1291 | 1311 |
| 1312 __ bind(&body); |
| 1292 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); | 1313 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); |
| 1293 __ bind(&body); | |
| 1294 Visit(stmt->body()); | 1314 Visit(stmt->body()); |
| 1295 | 1315 |
| 1296 // Emit the statement position here as this is where the while | 1316 // Emit the statement position here as this is where the while |
| 1297 // statement code starts. | 1317 // statement code starts. |
| 1298 __ bind(loop_statement.continue_label()); | 1318 __ bind(loop_statement.continue_label()); |
| 1299 SetStatementPosition(stmt); | 1319 SetStatementPosition(stmt); |
| 1300 | 1320 |
| 1301 // Check stack before looping. | 1321 // Check stack before looping. |
| 1302 EmitBackEdgeBookkeeping(stmt, &body); | 1322 EmitBackEdgeBookkeeping(stmt, &body); |
| 1303 | 1323 |
| 1304 __ bind(&test); | 1324 __ bind(&test); |
| 1305 VisitForControl(stmt->cond(), | 1325 VisitForControl(stmt->cond(), |
| 1306 &body, | 1326 &body, |
| 1307 loop_statement.break_label(), | 1327 loop_statement.break_label(), |
| 1308 loop_statement.break_label()); | 1328 loop_statement.break_label()); |
| 1309 | 1329 |
| 1330 __ bind(loop_statement.break_label()); |
| 1310 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 1331 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 1311 __ bind(loop_statement.break_label()); | |
| 1312 decrement_loop_depth(); | 1332 decrement_loop_depth(); |
| 1313 } | 1333 } |
| 1314 | 1334 |
| 1315 | 1335 |
| 1316 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) { | 1336 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) { |
| 1317 Comment cmnt(masm_, "[ ForStatement"); | 1337 Comment cmnt(masm_, "[ ForStatement"); |
| 1318 Label test, body; | 1338 Label test, body; |
| 1319 | 1339 |
| 1320 Iteration loop_statement(this, stmt); | 1340 Iteration loop_statement(this, stmt); |
| 1321 | 1341 |
| 1322 // Set statement position for a break slot before entering the for-body. | 1342 // Set statement position for a break slot before entering the for-body. |
| 1323 SetStatementPosition(stmt); | 1343 SetStatementPosition(stmt); |
| 1324 | 1344 |
| 1325 if (stmt->init() != NULL) { | 1345 if (stmt->init() != NULL) { |
| 1326 Visit(stmt->init()); | 1346 Visit(stmt->init()); |
| 1327 } | 1347 } |
| 1328 | 1348 |
| 1329 increment_loop_depth(); | 1349 increment_loop_depth(); |
| 1330 // Emit the test at the bottom of the loop (even if empty). | 1350 // Emit the test at the bottom of the loop (even if empty). |
| 1331 __ jmp(&test); | 1351 __ jmp(&test); |
| 1332 | 1352 |
| 1353 __ bind(&body); |
| 1333 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); | 1354 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); |
| 1334 __ bind(&body); | |
| 1335 Visit(stmt->body()); | 1355 Visit(stmt->body()); |
| 1336 | 1356 |
| 1357 __ bind(loop_statement.continue_label()); |
| 1337 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); | 1358 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); |
| 1338 __ bind(loop_statement.continue_label()); | |
| 1339 if (stmt->next() != NULL) { | 1359 if (stmt->next() != NULL) { |
| 1340 Visit(stmt->next()); | 1360 Visit(stmt->next()); |
| 1341 } | 1361 } |
| 1342 | 1362 |
| 1343 // Emit the statement position here as this is where the for | 1363 // Emit the statement position here as this is where the for |
| 1344 // statement code starts. | 1364 // statement code starts. |
| 1345 SetStatementPosition(stmt); | 1365 SetStatementPosition(stmt); |
| 1346 | 1366 |
| 1347 // Check stack before looping. | 1367 // Check stack before looping. |
| 1348 EmitBackEdgeBookkeeping(stmt, &body); | 1368 EmitBackEdgeBookkeeping(stmt, &body); |
| 1349 | 1369 |
| 1350 __ bind(&test); | 1370 __ bind(&test); |
| 1351 if (stmt->cond() != NULL) { | 1371 if (stmt->cond() != NULL) { |
| 1352 VisitForControl(stmt->cond(), | 1372 VisitForControl(stmt->cond(), |
| 1353 &body, | 1373 &body, |
| 1354 loop_statement.break_label(), | 1374 loop_statement.break_label(), |
| 1355 loop_statement.break_label()); | 1375 loop_statement.break_label()); |
| 1356 } else { | 1376 } else { |
| 1357 __ jmp(&body); | 1377 __ jmp(&body); |
| 1358 } | 1378 } |
| 1359 | 1379 |
| 1380 __ bind(loop_statement.break_label()); |
| 1360 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 1381 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 1361 __ bind(loop_statement.break_label()); | |
| 1362 decrement_loop_depth(); | 1382 decrement_loop_depth(); |
| 1363 } | 1383 } |
| 1364 | 1384 |
| 1365 | 1385 |
| 1366 void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1386 void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 1367 Comment cmnt(masm_, "[ TryCatchStatement"); | 1387 Comment cmnt(masm_, "[ TryCatchStatement"); |
| 1368 SetStatementPosition(stmt); | 1388 SetStatementPosition(stmt); |
| 1369 // The try block adds a handler to the exception handler chain before | 1389 // The try block adds a handler to the exception handler chain before |
| 1370 // entering, and removes it again when exiting normally. If an exception | 1390 // entering, and removes it again when exiting normally. If an exception |
| 1371 // is thrown during execution of the try block, the handler is consumed | 1391 // is thrown during execution of the try block, the handler is consumed |
| 1372 // and control is passed to the catch block with the exception in the | 1392 // and control is passed to the catch block with the exception in the |
| 1373 // result register. | 1393 // result register. |
| 1374 | 1394 |
| 1375 Label try_entry, handler_entry, exit; | 1395 Label try_entry, handler_entry, exit; |
| 1376 __ jmp(&try_entry); | 1396 __ jmp(&try_entry); |
| 1377 __ bind(&handler_entry); | 1397 __ bind(&handler_entry); |
| 1378 handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos())); | 1398 handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos())); |
| 1379 // Exception handler code, the exception is in the result register. | 1399 // Exception handler code, the exception is in the result register. |
| 1380 // Extend the context before executing the catch block. | 1400 // Extend the context before executing the catch block. |
| 1381 { Comment cmnt(masm_, "[ Extend catch context"); | 1401 { Comment cmnt(masm_, "[ Extend catch context"); |
| 1382 __ Push(stmt->variable()->name()); | 1402 AsmPushHandle(stmt->variable()->name()); |
| 1383 __ Push(result_register()); | 1403 AsmPush(result_register()); |
| 1384 PushFunctionArgumentForContextAllocation(); | 1404 PushFunctionArgumentForContextAllocation(); |
| 1385 __ CallRuntime(Runtime::kHiddenPushCatchContext, 3); | 1405 AsmCallRuntime(Runtime::kHiddenPushCatchContext, 3); |
| 1386 StoreToFrameField(StandardFrameConstants::kContextOffset, | 1406 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 1387 context_register()); | 1407 context_register()); |
| 1388 } | 1408 } |
| 1389 | 1409 |
| 1390 Scope* saved_scope = scope(); | 1410 Scope* saved_scope = scope(); |
| 1391 scope_ = stmt->scope(); | 1411 scope_ = stmt->scope(); |
| 1392 ASSERT(scope_->declarations()->is_empty()); | 1412 ASSERT(scope_->declarations()->is_empty()); |
| 1393 { WithOrCatch catch_body(this); | 1413 { WithOrCatch catch_body(this); |
| 1394 Visit(stmt->catch_block()); | 1414 Visit(stmt->catch_block()); |
| 1395 } | 1415 } |
| 1396 // Restore the context. | 1416 // Restore the context. |
| 1397 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 1417 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 1398 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 1418 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
| 1399 scope_ = saved_scope; | 1419 scope_ = saved_scope; |
| 1400 __ jmp(&exit); | 1420 __ jmp(&exit); |
| 1401 | 1421 |
| 1402 // Try block code. Sets up the exception handler chain. | 1422 // Try block code. Sets up the exception handler chain. |
| 1403 __ bind(&try_entry); | 1423 __ bind(&try_entry); |
| 1404 __ PushTryHandler(StackHandler::CATCH, stmt->index()); | 1424 AsmPushTryHandler(StackHandler::CATCH, stmt->index()); |
| 1405 { TryCatch try_body(this); | 1425 { TryCatch try_body(this); |
| 1406 Visit(stmt->try_block()); | 1426 Visit(stmt->try_block()); |
| 1407 } | 1427 } |
| 1408 __ PopTryHandler(); | 1428 AsmPopTryHandler(); |
| 1409 __ bind(&exit); | 1429 __ bind(&exit); |
| 1410 } | 1430 } |
| 1411 | 1431 |
| 1412 | 1432 |
| 1413 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 1433 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 1414 Comment cmnt(masm_, "[ TryFinallyStatement"); | 1434 Comment cmnt(masm_, "[ TryFinallyStatement"); |
| 1415 SetStatementPosition(stmt); | 1435 SetStatementPosition(stmt); |
| 1416 // Try finally is compiled by setting up a try-handler on the stack while | 1436 // Try finally is compiled by setting up a try-handler on the stack while |
| 1417 // executing the try body, and removing it again afterwards. | 1437 // executing the try body, and removing it again afterwards. |
| 1418 // | 1438 // |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1438 | 1458 |
| 1439 // Jump to try-handler setup and try-block code. | 1459 // Jump to try-handler setup and try-block code. |
| 1440 __ jmp(&try_entry); | 1460 __ jmp(&try_entry); |
| 1441 __ bind(&handler_entry); | 1461 __ bind(&handler_entry); |
| 1442 handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos())); | 1462 handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos())); |
| 1443 // Exception handler code. This code is only executed when an exception | 1463 // Exception handler code. This code is only executed when an exception |
| 1444 // is thrown. The exception is in the result register, and must be | 1464 // is thrown. The exception is in the result register, and must be |
| 1445 // preserved by the finally block. Call the finally block and then | 1465 // preserved by the finally block. Call the finally block and then |
| 1446 // rethrow the exception if it returns. | 1466 // rethrow the exception if it returns. |
| 1447 __ Call(&finally_entry); | 1467 __ Call(&finally_entry); |
| 1448 __ Push(result_register()); | 1468 AsmPush(result_register()); |
| 1449 __ CallRuntime(Runtime::kHiddenReThrow, 1); | 1469 AsmCallRuntime(Runtime::kHiddenReThrow, 1); |
| 1450 | 1470 |
| 1451 // Finally block implementation. | 1471 // Finally block implementation. |
| 1452 __ bind(&finally_entry); | 1472 __ bind(&finally_entry); |
| 1473 // The return address is on the stack -> update the height |
| 1474 UpdateStackHeight(1); |
| 1453 EnterFinallyBlock(); | 1475 EnterFinallyBlock(); |
| 1454 { Finally finally_body(this); | 1476 { Finally finally_body(this); |
| 1455 Visit(stmt->finally_block()); | 1477 Visit(stmt->finally_block()); |
| 1456 } | 1478 } |
| 1457 ExitFinallyBlock(); // Return to the calling code. | 1479 ExitFinallyBlock(); // Return to the calling code. |
| 1458 | 1480 |
| 1459 // Set up try handler. | 1481 // Set up try handler. |
| 1460 __ bind(&try_entry); | 1482 __ bind(&try_entry); |
| 1461 __ PushTryHandler(StackHandler::FINALLY, stmt->index()); | 1483 AsmPushTryHandler(StackHandler::FINALLY, stmt->index()); |
| 1462 { TryFinally try_body(this, &finally_entry); | 1484 { TryFinally try_body(this, &finally_entry); |
| 1463 Visit(stmt->try_block()); | 1485 Visit(stmt->try_block()); |
| 1464 } | 1486 } |
| 1465 __ PopTryHandler(); | 1487 AsmPopTryHandler(); |
| 1466 // Execute the finally block on the way out. Clobber the unpredictable | 1488 // Execute the finally block on the way out. Clobber the unpredictable |
| 1467 // value in the result register with one that's safe for GC because the | 1489 // value in the result register with one that's safe for GC because the |
| 1468 // finally block will unconditionally preserve the result register on the | 1490 // finally block will unconditionally preserve the result register on the |
| 1469 // stack. | 1491 // stack. |
| 1470 ClearAccumulator(); | 1492 ClearAccumulator(); |
| 1471 __ Call(&finally_entry); | 1493 __ Call(&finally_entry); |
| 1472 } | 1494 } |
| 1473 | 1495 |
| 1474 | 1496 |
| 1475 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1497 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 1476 Comment cmnt(masm_, "[ DebuggerStatement"); | 1498 Comment cmnt(masm_, "[ DebuggerStatement"); |
| 1477 SetStatementPosition(stmt); | 1499 SetStatementPosition(stmt); |
| 1478 | 1500 |
| 1479 __ DebugBreak(); | 1501 __ DebugBreak(); |
| 1480 // Ignore the return value. | 1502 // Ignore the return value. |
| 1481 } | 1503 } |
| 1482 | 1504 |
| 1483 | 1505 |
| 1484 void FullCodeGenerator::VisitCaseClause(CaseClause* clause) { | 1506 void FullCodeGenerator::VisitCaseClause(CaseClause* clause) { |
| 1485 UNREACHABLE(); | 1507 UNREACHABLE(); |
| 1486 } | 1508 } |
| 1487 | 1509 |
| 1488 | 1510 |
| 1489 void FullCodeGenerator::VisitConditional(Conditional* expr) { | 1511 void FullCodeGenerator::VisitConditional(Conditional* expr) { |
| 1490 Comment cmnt(masm_, "[ Conditional"); | 1512 Comment cmnt(masm_, "[ Conditional"); |
| 1491 Label true_case, false_case, done; | 1513 Label true_case, false_case, done; |
| 1492 VisitForControl(expr->condition(), &true_case, &false_case, &true_case); | 1514 VisitForControl(expr->condition(), &true_case, &false_case, &true_case); |
| 1515 StackHeightWrapper if_stack_height = CurrentStackHeight(); |
| 1493 | 1516 |
| 1517 __ bind(&true_case); |
| 1494 PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS); | 1518 PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS); |
| 1495 __ bind(&true_case); | |
| 1496 SetExpressionPosition(expr->then_expression()); | 1519 SetExpressionPosition(expr->then_expression()); |
| 1497 if (context()->IsTest()) { | 1520 if (context()->IsTest()) { |
| 1498 const TestContext* for_test = TestContext::cast(context()); | 1521 const TestContext* for_test = TestContext::cast(context()); |
| 1499 VisitForControl(expr->then_expression(), | 1522 VisitForControl(expr->then_expression(), |
| 1500 for_test->true_label(), | 1523 for_test->true_label(), |
| 1501 for_test->false_label(), | 1524 for_test->false_label(), |
| 1502 NULL); | 1525 NULL); |
| 1503 } else { | 1526 } else { |
| 1504 VisitInDuplicateContext(expr->then_expression()); | 1527 VisitInDuplicateContext(expr->then_expression()); |
| 1505 __ jmp(&done); | 1528 __ jmp(&done); |
| 1506 } | 1529 } |
| 1507 | 1530 |
| 1531 __ bind(&false_case); |
| 1532 SetStackHeight(if_stack_height); |
| 1508 PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS); | 1533 PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS); |
| 1509 __ bind(&false_case); | |
| 1510 SetExpressionPosition(expr->else_expression()); | 1534 SetExpressionPosition(expr->else_expression()); |
| 1511 VisitInDuplicateContext(expr->else_expression()); | 1535 VisitInDuplicateContext(expr->else_expression()); |
| 1512 // If control flow falls through Visit, merge it with true case here. | 1536 // If control flow falls through Visit, merge it with true case here. |
| 1513 if (!context()->IsTest()) { | 1537 if (!context()->IsTest()) { |
| 1514 __ bind(&done); | 1538 __ bind(&done); |
| 1515 } | 1539 } |
| 1516 } | 1540 } |
| 1517 | 1541 |
| 1518 | 1542 |
| 1519 void FullCodeGenerator::VisitLiteral(Literal* expr) { | 1543 void FullCodeGenerator::VisitLiteral(Literal* expr) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1565 int parameters = fun->shared()->formal_parameter_count(); | 1589 int parameters = fun->shared()->formal_parameter_count(); |
| 1566 shared->set_formal_parameter_count(parameters); | 1590 shared->set_formal_parameter_count(parameters); |
| 1567 | 1591 |
| 1568 EmitNewClosure(shared, false); | 1592 EmitNewClosure(shared, false); |
| 1569 } | 1593 } |
| 1570 | 1594 |
| 1571 | 1595 |
| 1572 void FullCodeGenerator::VisitThrow(Throw* expr) { | 1596 void FullCodeGenerator::VisitThrow(Throw* expr) { |
| 1573 Comment cmnt(masm_, "[ Throw"); | 1597 Comment cmnt(masm_, "[ Throw"); |
| 1574 VisitForStackValue(expr->exception()); | 1598 VisitForStackValue(expr->exception()); |
| 1575 __ CallRuntime(Runtime::kHiddenThrow, 1); | 1599 AsmCallRuntime(Runtime::kHiddenThrow, 1); |
| 1576 // Never returns here. | 1600 // Never returns here. Update stack height so that we do not confuse the |
| 1601 // stack height checker. |
| 1602 if (context() != NULL && !context()->IsEffect()) { |
| 1603 UpdateStackHeight(1); |
| 1604 } |
| 1577 } | 1605 } |
| 1578 | 1606 |
| 1579 | 1607 |
| 1580 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit( | 1608 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit( |
| 1581 int* stack_depth, | 1609 int* stack_depth, |
| 1582 int* context_length) { | 1610 int* context_length) { |
| 1583 // The macros used here must preserve the result register. | 1611 // The macros used here must preserve the result register. |
| 1584 __ Drop(*stack_depth); | 1612 codegen()->AsmDrop(*stack_depth); |
| 1585 __ PopTryHandler(); | 1613 codegen()->AsmPopTryHandler(); |
| 1586 *stack_depth = 0; | 1614 *stack_depth = 0; |
| 1587 return previous_; | 1615 return previous_; |
| 1588 } | 1616 } |
| 1589 | 1617 |
| 1590 | 1618 |
| 1591 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) { | 1619 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) { |
| 1592 Expression* sub_expr; | 1620 Expression* sub_expr; |
| 1593 Handle<String> check; | 1621 Handle<String> check; |
| 1594 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { | 1622 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { |
| 1595 EmitLiteralCompareTypeof(expr, sub_expr, check); | 1623 EmitLiteralCompareTypeof(expr, sub_expr, check); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1697 } | 1725 } |
| 1698 return true; | 1726 return true; |
| 1699 } | 1727 } |
| 1700 #endif // DEBUG | 1728 #endif // DEBUG |
| 1701 | 1729 |
| 1702 | 1730 |
| 1703 #undef __ | 1731 #undef __ |
| 1704 | 1732 |
| 1705 | 1733 |
| 1706 } } // namespace v8::internal | 1734 } } // namespace v8::internal |
| OLD | NEW |