| 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 "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
| 8 | 8 |
| 9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 1900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1911 if (result_saved) { | 1911 if (result_saved) { |
| 1912 __ Drop(1); // literal index | 1912 __ Drop(1); // literal index |
| 1913 context()->PlugTOS(); | 1913 context()->PlugTOS(); |
| 1914 } else { | 1914 } else { |
| 1915 context()->Plug(eax); | 1915 context()->Plug(eax); |
| 1916 } | 1916 } |
| 1917 } | 1917 } |
| 1918 | 1918 |
| 1919 | 1919 |
| 1920 void FullCodeGenerator::VisitAssignment(Assignment* expr) { | 1920 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
| 1921 DCHECK(expr->target()->IsValidReferenceExpression()); | 1921 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); |
| 1922 | 1922 |
| 1923 Comment cmnt(masm_, "[ Assignment"); | 1923 Comment cmnt(masm_, "[ Assignment"); |
| 1924 SetExpressionPosition(expr, INSERT_BREAK); | 1924 SetExpressionPosition(expr, INSERT_BREAK); |
| 1925 | 1925 |
| 1926 Property* property = expr->target()->AsProperty(); | 1926 Property* property = expr->target()->AsProperty(); |
| 1927 LhsKind assign_type = Property::GetAssignType(property); | 1927 LhsKind assign_type = Property::GetAssignType(property); |
| 1928 | 1928 |
| 1929 // Evaluate LHS expression. | 1929 // Evaluate LHS expression. |
| 1930 switch (assign_type) { | 1930 switch (assign_type) { |
| 1931 case VARIABLE: | 1931 case VARIABLE: |
| (...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2568 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); | 2568 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); |
| 2569 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2569 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2570 CallIC(code, expr->BinaryOperationFeedbackId()); | 2570 CallIC(code, expr->BinaryOperationFeedbackId()); |
| 2571 patch_site.EmitPatchInfo(); | 2571 patch_site.EmitPatchInfo(); |
| 2572 context()->Plug(eax); | 2572 context()->Plug(eax); |
| 2573 } | 2573 } |
| 2574 | 2574 |
| 2575 | 2575 |
| 2576 void FullCodeGenerator::EmitAssignment(Expression* expr, | 2576 void FullCodeGenerator::EmitAssignment(Expression* expr, |
| 2577 FeedbackVectorICSlot slot) { | 2577 FeedbackVectorICSlot slot) { |
| 2578 DCHECK(expr->IsValidReferenceExpression()); | 2578 DCHECK(expr->IsValidReferenceExpressionOrThis()); |
| 2579 | 2579 |
| 2580 Property* prop = expr->AsProperty(); | 2580 Property* prop = expr->AsProperty(); |
| 2581 LhsKind assign_type = Property::GetAssignType(prop); | 2581 LhsKind assign_type = Property::GetAssignType(prop); |
| 2582 | 2582 |
| 2583 switch (assign_type) { | 2583 switch (assign_type) { |
| 2584 case VARIABLE: { | 2584 case VARIABLE: { |
| 2585 Variable* var = expr->AsVariableProxy()->var(); | 2585 Variable* var = expr->AsVariableProxy()->var(); |
| 2586 EffectContext context(this); | 2586 EffectContext context(this); |
| 2587 EmitVariableAssignment(var, Token::ASSIGN, slot); | 2587 EmitVariableAssignment(var, Token::ASSIGN, slot); |
| 2588 break; | 2588 break; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2710 Label const_error; | 2710 Label const_error; |
| 2711 MemOperand location = VarOperand(var, ecx); | 2711 MemOperand location = VarOperand(var, ecx); |
| 2712 __ mov(edx, location); | 2712 __ mov(edx, location); |
| 2713 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2713 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2714 __ j(not_equal, &const_error, Label::kNear); | 2714 __ j(not_equal, &const_error, Label::kNear); |
| 2715 __ push(Immediate(var->name())); | 2715 __ push(Immediate(var->name())); |
| 2716 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2716 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2717 __ bind(&const_error); | 2717 __ bind(&const_error); |
| 2718 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2718 __ CallRuntime(Runtime::kThrowConstAssignError, 0); |
| 2719 | 2719 |
| 2720 } else if (var->is_this() && op == Token::INIT_CONST) { |
| 2721 // Initializing assignment to const {this} needs a write barrier. |
| 2722 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2723 Label uninitialized_this; |
| 2724 MemOperand location = VarOperand(var, ecx); |
| 2725 __ mov(edx, location); |
| 2726 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2727 __ j(equal, &uninitialized_this); |
| 2728 __ push(Immediate(var->name())); |
| 2729 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2730 __ bind(&uninitialized_this); |
| 2731 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2732 |
| 2720 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2733 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
| 2721 if (var->IsLookupSlot()) { | 2734 if (var->IsLookupSlot()) { |
| 2722 // Assignment to var. | 2735 // Assignment to var. |
| 2723 __ push(eax); // Value. | 2736 __ push(eax); // Value. |
| 2724 __ push(esi); // Context. | 2737 __ push(esi); // Context. |
| 2725 __ push(Immediate(var->name())); | 2738 __ push(Immediate(var->name())); |
| 2726 __ push(Immediate(Smi::FromInt(language_mode()))); | 2739 __ push(Immediate(Smi::FromInt(language_mode()))); |
| 2727 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2740 __ CallRuntime(Runtime::kStoreLookupSlot, 4); |
| 2728 } else { | 2741 } else { |
| 2729 // Assignment to var or initializing assignment to let/const in harmony | 2742 // Assignment to var or initializing assignment to let/const in harmony |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3052 __ push(Immediate(Smi::FromInt(language_mode()))); | 3065 __ push(Immediate(Smi::FromInt(language_mode()))); |
| 3053 | 3066 |
| 3054 // Push the start position of the scope the calls resides in. | 3067 // Push the start position of the scope the calls resides in. |
| 3055 __ push(Immediate(Smi::FromInt(scope()->start_position()))); | 3068 __ push(Immediate(Smi::FromInt(scope()->start_position()))); |
| 3056 | 3069 |
| 3057 // Do the runtime call. | 3070 // Do the runtime call. |
| 3058 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 3071 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
| 3059 } | 3072 } |
| 3060 | 3073 |
| 3061 | 3074 |
| 3062 void FullCodeGenerator::EmitInitializeThisAfterSuper( | |
| 3063 SuperCallReference* super_call_ref, FeedbackVectorICSlot slot) { | |
| 3064 Variable* this_var = super_call_ref->this_var()->var(); | |
| 3065 GetVar(ecx, this_var); | |
| 3066 __ cmp(ecx, isolate()->factory()->the_hole_value()); | |
| 3067 | |
| 3068 Label uninitialized_this; | |
| 3069 __ j(equal, &uninitialized_this); | |
| 3070 __ push(Immediate(this_var->name())); | |
| 3071 __ CallRuntime(Runtime::kThrowReferenceError, 1); | |
| 3072 __ bind(&uninitialized_this); | |
| 3073 | |
| 3074 EmitVariableAssignment(this_var, Token::INIT_CONST, slot); | |
| 3075 } | |
| 3076 | |
| 3077 | |
| 3078 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. | 3075 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. |
| 3079 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { | 3076 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
| 3080 VariableProxy* callee = expr->expression()->AsVariableProxy(); | 3077 VariableProxy* callee = expr->expression()->AsVariableProxy(); |
| 3081 if (callee->var()->IsLookupSlot()) { | 3078 if (callee->var()->IsLookupSlot()) { |
| 3082 Label slow, done; | 3079 Label slow, done; |
| 3083 SetExpressionPosition(callee); | 3080 SetExpressionPosition(callee); |
| 3084 // Generate code for loading from variables potentially shadowed by | 3081 // Generate code for loading from variables potentially shadowed by |
| 3085 // eval-introduced variables. | 3082 // eval-introduced variables. |
| 3086 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | 3083 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); |
| 3087 | 3084 |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3283 } | 3280 } |
| 3284 | 3281 |
| 3285 __ LoadHeapObject(ebx, FeedbackVector()); | 3282 __ LoadHeapObject(ebx, FeedbackVector()); |
| 3286 __ mov(edx, Immediate(SmiFromSlot(expr->CallFeedbackSlot()))); | 3283 __ mov(edx, Immediate(SmiFromSlot(expr->CallFeedbackSlot()))); |
| 3287 | 3284 |
| 3288 CallConstructStub stub(isolate(), SUPER_CALL_RECORD_TARGET); | 3285 CallConstructStub stub(isolate(), SUPER_CALL_RECORD_TARGET); |
| 3289 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 3286 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
| 3290 | 3287 |
| 3291 RecordJSReturnSite(expr); | 3288 RecordJSReturnSite(expr); |
| 3292 | 3289 |
| 3293 EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot()); | |
| 3294 context()->Plug(eax); | 3290 context()->Plug(eax); |
| 3295 } | 3291 } |
| 3296 | 3292 |
| 3297 | 3293 |
| 3298 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 3294 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
| 3299 ZoneList<Expression*>* args = expr->arguments(); | 3295 ZoneList<Expression*>* args = expr->arguments(); |
| 3300 DCHECK(args->length() == 1); | 3296 DCHECK(args->length() == 1); |
| 3301 | 3297 |
| 3302 VisitForAccumulatorValue(args->at(0)); | 3298 VisitForAccumulatorValue(args->at(0)); |
| 3303 | 3299 |
| (...skipping 1354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4658 | 4654 |
| 4659 // Push NewTarget | 4655 // Push NewTarget |
| 4660 DCHECK(args->at(2)->IsVariableProxy()); | 4656 DCHECK(args->at(2)->IsVariableProxy()); |
| 4661 VisitForStackValue(args->at(2)); | 4657 VisitForStackValue(args->at(2)); |
| 4662 | 4658 |
| 4663 EmitCallJSRuntimeFunction(call); | 4659 EmitCallJSRuntimeFunction(call); |
| 4664 | 4660 |
| 4665 // Restore context register. | 4661 // Restore context register. |
| 4666 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4662 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 4667 context()->DropAndPlug(1, eax); | 4663 context()->DropAndPlug(1, eax); |
| 4668 | |
| 4669 // TODO(mvstanton): with FLAG_vector_stores this needs a slot id. | |
| 4670 EmitInitializeThisAfterSuper(super_call_ref); | |
| 4671 } | 4664 } |
| 4672 | 4665 |
| 4673 | 4666 |
| 4674 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { | 4667 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
| 4675 // Push the builtins object as receiver. | 4668 // Push the builtins object as receiver. |
| 4676 __ mov(eax, GlobalObjectOperand()); | 4669 __ mov(eax, GlobalObjectOperand()); |
| 4677 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); | 4670 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); |
| 4678 | 4671 |
| 4679 // Load the function from the receiver. | 4672 // Load the function from the receiver. |
| 4680 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); | 4673 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4859 break; | 4852 break; |
| 4860 } | 4853 } |
| 4861 | 4854 |
| 4862 default: | 4855 default: |
| 4863 UNREACHABLE(); | 4856 UNREACHABLE(); |
| 4864 } | 4857 } |
| 4865 } | 4858 } |
| 4866 | 4859 |
| 4867 | 4860 |
| 4868 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { | 4861 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
| 4869 DCHECK(expr->expression()->IsValidReferenceExpression()); | 4862 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis()); |
| 4870 | 4863 |
| 4871 Comment cmnt(masm_, "[ CountOperation"); | 4864 Comment cmnt(masm_, "[ CountOperation"); |
| 4872 | 4865 |
| 4873 Property* prop = expr->expression()->AsProperty(); | 4866 Property* prop = expr->expression()->AsProperty(); |
| 4874 LhsKind assign_type = Property::GetAssignType(prop); | 4867 LhsKind assign_type = Property::GetAssignType(prop); |
| 4875 | 4868 |
| 4876 // Evaluate expression and get value. | 4869 // Evaluate expression and get value. |
| 4877 if (assign_type == VARIABLE) { | 4870 if (assign_type == VARIABLE) { |
| 4878 DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); | 4871 DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); |
| 4879 AccumulatorValueContext context(this); | 4872 AccumulatorValueContext context(this); |
| (...skipping 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5491 Assembler::target_address_at(call_target_address, | 5484 Assembler::target_address_at(call_target_address, |
| 5492 unoptimized_code)); | 5485 unoptimized_code)); |
| 5493 return OSR_AFTER_STACK_CHECK; | 5486 return OSR_AFTER_STACK_CHECK; |
| 5494 } | 5487 } |
| 5495 | 5488 |
| 5496 | 5489 |
| 5497 } // namespace internal | 5490 } // namespace internal |
| 5498 } // namespace v8 | 5491 } // namespace v8 |
| 5499 | 5492 |
| 5500 #endif // V8_TARGET_ARCH_X87 | 5493 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |