| 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 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
| 6 | 6 |
| 7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 | 416 |
| 417 SetReturnPosition(literal()); | 417 SetReturnPosition(literal()); |
| 418 __ leave(); | 418 __ leave(); |
| 419 | 419 |
| 420 int arg_count = info_->scope()->num_parameters() + 1; | 420 int arg_count = info_->scope()->num_parameters() + 1; |
| 421 int arguments_bytes = arg_count * kPointerSize; | 421 int arguments_bytes = arg_count * kPointerSize; |
| 422 __ Ret(arguments_bytes, ecx); | 422 __ Ret(arguments_bytes, ecx); |
| 423 } | 423 } |
| 424 } | 424 } |
| 425 | 425 |
| 426 void FullCodeGenerator::RestoreContext() { |
| 427 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 428 } |
| 426 | 429 |
| 427 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 430 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
| 428 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 431 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 429 MemOperand operand = codegen()->VarOperand(var, result_register()); | 432 MemOperand operand = codegen()->VarOperand(var, result_register()); |
| 430 // Memory operands can be pushed directly. | 433 // Memory operands can be pushed directly. |
| 431 codegen()->PushOperand(operand); | 434 codegen()->PushOperand(operand); |
| 432 } | 435 } |
| 433 | 436 |
| 434 | 437 |
| 435 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { | 438 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
| (...skipping 904 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1340 __ push(Immediate(constant_properties)); | 1343 __ push(Immediate(constant_properties)); |
| 1341 __ push(Immediate(Smi::FromInt(flags))); | 1344 __ push(Immediate(Smi::FromInt(flags))); |
| 1342 __ CallRuntime(Runtime::kCreateObjectLiteral); | 1345 __ CallRuntime(Runtime::kCreateObjectLiteral); |
| 1343 } else { | 1346 } else { |
| 1344 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1347 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1345 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); | 1348 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); |
| 1346 __ mov(ecx, Immediate(constant_properties)); | 1349 __ mov(ecx, Immediate(constant_properties)); |
| 1347 __ mov(edx, Immediate(Smi::FromInt(flags))); | 1350 __ mov(edx, Immediate(Smi::FromInt(flags))); |
| 1348 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); | 1351 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); |
| 1349 __ CallStub(&stub); | 1352 __ CallStub(&stub); |
| 1350 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1353 RestoreContext(); |
| 1351 } | 1354 } |
| 1352 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1355 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
| 1353 | 1356 |
| 1354 // If result_saved is true the result is on top of the stack. If | 1357 // If result_saved is true the result is on top of the stack. If |
| 1355 // result_saved is false the result is in eax. | 1358 // result_saved is false the result is in eax. |
| 1356 bool result_saved = false; | 1359 bool result_saved = false; |
| 1357 | 1360 |
| 1358 AccessorTable accessor_table(zone()); | 1361 AccessorTable accessor_table(zone()); |
| 1359 int property_index = 0; | 1362 int property_index = 0; |
| 1360 for (; property_index < expr->properties()->length(); property_index++) { | 1363 for (; property_index < expr->properties()->length(); property_index++) { |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1775 Immediate(Smi::FromInt(continuation.pos()))); | 1778 Immediate(Smi::FromInt(continuation.pos()))); |
| 1776 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); | 1779 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); |
| 1777 __ mov(ecx, esi); | 1780 __ mov(ecx, esi); |
| 1778 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, | 1781 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, |
| 1779 kDontSaveFPRegs); | 1782 kDontSaveFPRegs); |
| 1780 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); | 1783 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); |
| 1781 __ cmp(esp, ebx); | 1784 __ cmp(esp, ebx); |
| 1782 __ j(equal, &post_runtime); | 1785 __ j(equal, &post_runtime); |
| 1783 __ push(eax); // generator object | 1786 __ push(eax); // generator object |
| 1784 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1787 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 1785 __ mov(context_register(), | 1788 RestoreContext(); |
| 1786 Operand(ebp, StandardFrameConstants::kContextOffset)); | |
| 1787 __ bind(&post_runtime); | 1789 __ bind(&post_runtime); |
| 1788 PopOperand(result_register()); | 1790 PopOperand(result_register()); |
| 1789 EmitReturnSequence(); | 1791 EmitReturnSequence(); |
| 1790 | 1792 |
| 1791 __ bind(&resume); | 1793 __ bind(&resume); |
| 1792 context()->Plug(result_register()); | 1794 context()->Plug(result_register()); |
| 1793 } | 1795 } |
| 1794 | 1796 |
| 1795 void FullCodeGenerator::PushOperand(MemOperand operand) { | 1797 void FullCodeGenerator::PushOperand(MemOperand operand) { |
| 1796 OperandStackDepthIncrement(1); | 1798 OperandStackDepthIncrement(1); |
| (...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2417 CodeFactory::CallIC(isolate(), arg_count, mode, expr->tail_call_mode()) | 2419 CodeFactory::CallIC(isolate(), arg_count, mode, expr->tail_call_mode()) |
| 2418 .code(); | 2420 .code(); |
| 2419 __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot()))); | 2421 __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot()))); |
| 2420 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2422 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| 2421 // Don't assign a type feedback id to the IC, since type feedback is provided | 2423 // Don't assign a type feedback id to the IC, since type feedback is provided |
| 2422 // by the vector above. | 2424 // by the vector above. |
| 2423 CallIC(ic); | 2425 CallIC(ic); |
| 2424 OperandStackDepthDecrement(arg_count + 1); | 2426 OperandStackDepthDecrement(arg_count + 1); |
| 2425 | 2427 |
| 2426 RecordJSReturnSite(expr); | 2428 RecordJSReturnSite(expr); |
| 2427 | 2429 RestoreContext(); |
| 2428 // Restore context register. | |
| 2429 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
| 2430 | |
| 2431 context()->DropAndPlug(1, eax); | 2430 context()->DropAndPlug(1, eax); |
| 2432 } | 2431 } |
| 2433 | 2432 |
| 2434 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { | 2433 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { |
| 2435 int arg_count = expr->arguments()->length(); | 2434 int arg_count = expr->arguments()->length(); |
| 2436 // Push copy of the first argument or undefined if it doesn't exist. | 2435 // Push copy of the first argument or undefined if it doesn't exist. |
| 2437 if (arg_count > 0) { | 2436 if (arg_count > 0) { |
| 2438 __ push(Operand(esp, arg_count * kPointerSize)); | 2437 __ push(Operand(esp, arg_count * kPointerSize)); |
| 2439 } else { | 2438 } else { |
| 2440 __ push(Immediate(isolate()->factory()->undefined_value())); | 2439 __ push(Immediate(isolate()->factory()->undefined_value())); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2522 PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS); | 2521 PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS); |
| 2523 | 2522 |
| 2524 SetCallPosition(expr); | 2523 SetCallPosition(expr); |
| 2525 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2524 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| 2526 __ Set(eax, arg_count); | 2525 __ Set(eax, arg_count); |
| 2527 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 2526 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
| 2528 expr->tail_call_mode()), | 2527 expr->tail_call_mode()), |
| 2529 RelocInfo::CODE_TARGET); | 2528 RelocInfo::CODE_TARGET); |
| 2530 OperandStackDepthDecrement(arg_count + 1); | 2529 OperandStackDepthDecrement(arg_count + 1); |
| 2531 RecordJSReturnSite(expr); | 2530 RecordJSReturnSite(expr); |
| 2532 // Restore context register. | 2531 RestoreContext(); |
| 2533 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
| 2534 context()->DropAndPlug(1, eax); | 2532 context()->DropAndPlug(1, eax); |
| 2535 } | 2533 } |
| 2536 | 2534 |
| 2537 | 2535 |
| 2538 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2536 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
| 2539 Comment cmnt(masm_, "[ CallNew"); | 2537 Comment cmnt(masm_, "[ CallNew"); |
| 2540 // According to ECMA-262, section 11.2.2, page 44, the function | 2538 // According to ECMA-262, section 11.2.2, page 44, the function |
| 2541 // expression in new calls must be evaluated before the | 2539 // expression in new calls must be evaluated before the |
| 2542 // arguments. | 2540 // arguments. |
| 2543 | 2541 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2563 __ mov(edi, Operand(esp, arg_count * kPointerSize)); | 2561 __ mov(edi, Operand(esp, arg_count * kPointerSize)); |
| 2564 | 2562 |
| 2565 // Record call targets in unoptimized code. | 2563 // Record call targets in unoptimized code. |
| 2566 __ EmitLoadTypeFeedbackVector(ebx); | 2564 __ EmitLoadTypeFeedbackVector(ebx); |
| 2567 __ mov(edx, Immediate(SmiFromSlot(expr->CallNewFeedbackSlot()))); | 2565 __ mov(edx, Immediate(SmiFromSlot(expr->CallNewFeedbackSlot()))); |
| 2568 | 2566 |
| 2569 CallConstructStub stub(isolate()); | 2567 CallConstructStub stub(isolate()); |
| 2570 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); | 2568 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 2571 OperandStackDepthDecrement(arg_count + 1); | 2569 OperandStackDepthDecrement(arg_count + 1); |
| 2572 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2570 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
| 2573 // Restore context register. | 2571 RestoreContext(); |
| 2574 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
| 2575 context()->Plug(eax); | 2572 context()->Plug(eax); |
| 2576 } | 2573 } |
| 2577 | 2574 |
| 2578 | 2575 |
| 2579 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { | 2576 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { |
| 2580 SuperCallReference* super_call_ref = | 2577 SuperCallReference* super_call_ref = |
| 2581 expr->expression()->AsSuperCallReference(); | 2578 expr->expression()->AsSuperCallReference(); |
| 2582 DCHECK_NOT_NULL(super_call_ref); | 2579 DCHECK_NOT_NULL(super_call_ref); |
| 2583 | 2580 |
| 2584 // Push the super constructor target on the stack (may be null, | 2581 // Push the super constructor target on the stack (may be null, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2605 __ mov(edx, result_register()); | 2602 __ mov(edx, result_register()); |
| 2606 | 2603 |
| 2607 // Load function and argument count into edi and eax. | 2604 // Load function and argument count into edi and eax. |
| 2608 __ Move(eax, Immediate(arg_count)); | 2605 __ Move(eax, Immediate(arg_count)); |
| 2609 __ mov(edi, Operand(esp, arg_count * kPointerSize)); | 2606 __ mov(edi, Operand(esp, arg_count * kPointerSize)); |
| 2610 | 2607 |
| 2611 __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 2608 __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 2612 OperandStackDepthDecrement(arg_count + 1); | 2609 OperandStackDepthDecrement(arg_count + 1); |
| 2613 | 2610 |
| 2614 RecordJSReturnSite(expr); | 2611 RecordJSReturnSite(expr); |
| 2615 | 2612 RestoreContext(); |
| 2616 // Restore context register. | |
| 2617 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
| 2618 context()->Plug(eax); | 2613 context()->Plug(eax); |
| 2619 } | 2614 } |
| 2620 | 2615 |
| 2621 | 2616 |
| 2622 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2617 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
| 2623 ZoneList<Expression*>* args = expr->arguments(); | 2618 ZoneList<Expression*>* args = expr->arguments(); |
| 2624 DCHECK(args->length() == 1); | 2619 DCHECK(args->length() == 1); |
| 2625 | 2620 |
| 2626 VisitForAccumulatorValue(args->at(0)); | 2621 VisitForAccumulatorValue(args->at(0)); |
| 2627 | 2622 |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3008 VisitForStackValue(arg); | 3003 VisitForStackValue(arg); |
| 3009 } | 3004 } |
| 3010 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); | 3005 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); |
| 3011 // Move target to edi. | 3006 // Move target to edi. |
| 3012 int const argc = args->length() - 2; | 3007 int const argc = args->length() - 2; |
| 3013 __ mov(edi, Operand(esp, (argc + 1) * kPointerSize)); | 3008 __ mov(edi, Operand(esp, (argc + 1) * kPointerSize)); |
| 3014 // Call the target. | 3009 // Call the target. |
| 3015 __ mov(eax, Immediate(argc)); | 3010 __ mov(eax, Immediate(argc)); |
| 3016 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 3011 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 3017 OperandStackDepthDecrement(argc + 1); | 3012 OperandStackDepthDecrement(argc + 1); |
| 3018 // Restore context register. | 3013 RestoreContext(); |
| 3019 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
| 3020 // Discard the function left on TOS. | 3014 // Discard the function left on TOS. |
| 3021 context()->DropAndPlug(1, eax); | 3015 context()->DropAndPlug(1, eax); |
| 3022 } | 3016 } |
| 3023 | 3017 |
| 3024 | 3018 |
| 3025 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3019 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
| 3026 ZoneList<Expression*>* args = expr->arguments(); | 3020 ZoneList<Expression*>* args = expr->arguments(); |
| 3027 DCHECK(args->length() == 1); | 3021 DCHECK(args->length() == 1); |
| 3028 | 3022 |
| 3029 VisitForAccumulatorValue(args->at(0)); | 3023 VisitForAccumulatorValue(args->at(0)); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3129 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { | 3123 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { |
| 3130 ZoneList<Expression*>* args = expr->arguments(); | 3124 ZoneList<Expression*>* args = expr->arguments(); |
| 3131 int arg_count = args->length(); | 3125 int arg_count = args->length(); |
| 3132 | 3126 |
| 3133 SetCallPosition(expr); | 3127 SetCallPosition(expr); |
| 3134 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 3128 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| 3135 __ Set(eax, arg_count); | 3129 __ Set(eax, arg_count); |
| 3136 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), | 3130 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), |
| 3137 RelocInfo::CODE_TARGET); | 3131 RelocInfo::CODE_TARGET); |
| 3138 OperandStackDepthDecrement(arg_count + 1); | 3132 OperandStackDepthDecrement(arg_count + 1); |
| 3139 | 3133 RestoreContext(); |
| 3140 // Restore context register. | |
| 3141 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
| 3142 } | 3134 } |
| 3143 | 3135 |
| 3144 | 3136 |
| 3145 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3137 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 3146 switch (expr->op()) { | 3138 switch (expr->op()) { |
| 3147 case Token::DELETE: { | 3139 case Token::DELETE: { |
| 3148 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3140 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 3149 Property* property = expr->expression()->AsProperty(); | 3141 Property* property = expr->expression()->AsProperty(); |
| 3150 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 3142 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 3151 | 3143 |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3605 Label* fall_through = NULL; | 3597 Label* fall_through = NULL; |
| 3606 context()->PrepareTest(&materialize_true, &materialize_false, | 3598 context()->PrepareTest(&materialize_true, &materialize_false, |
| 3607 &if_true, &if_false, &fall_through); | 3599 &if_true, &if_false, &fall_through); |
| 3608 | 3600 |
| 3609 Token::Value op = expr->op(); | 3601 Token::Value op = expr->op(); |
| 3610 VisitForStackValue(expr->left()); | 3602 VisitForStackValue(expr->left()); |
| 3611 switch (op) { | 3603 switch (op) { |
| 3612 case Token::IN: | 3604 case Token::IN: |
| 3613 VisitForStackValue(expr->right()); | 3605 VisitForStackValue(expr->right()); |
| 3614 SetExpressionPosition(expr); | 3606 SetExpressionPosition(expr); |
| 3615 CallRuntimeWithOperands(Runtime::kHasProperty); | 3607 EmitHasProperty(); |
| 3616 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); | 3608 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
| 3617 __ cmp(eax, isolate()->factory()->true_value()); | 3609 __ cmp(eax, isolate()->factory()->true_value()); |
| 3618 Split(equal, if_true, if_false, fall_through); | 3610 Split(equal, if_true, if_false, fall_through); |
| 3619 break; | 3611 break; |
| 3620 | 3612 |
| 3621 case Token::INSTANCEOF: { | 3613 case Token::INSTANCEOF: { |
| 3622 VisitForAccumulatorValue(expr->right()); | 3614 VisitForAccumulatorValue(expr->right()); |
| 3623 SetExpressionPosition(expr); | 3615 SetExpressionPosition(expr); |
| 3624 PopOperand(edx); | 3616 PopOperand(edx); |
| 3625 InstanceOfStub stub(isolate()); | 3617 InstanceOfStub stub(isolate()); |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3871 isolate->builtins()->OnStackReplacement()->entry(), | 3863 isolate->builtins()->OnStackReplacement()->entry(), |
| 3872 Assembler::target_address_at(call_target_address, unoptimized_code)); | 3864 Assembler::target_address_at(call_target_address, unoptimized_code)); |
| 3873 return ON_STACK_REPLACEMENT; | 3865 return ON_STACK_REPLACEMENT; |
| 3874 } | 3866 } |
| 3875 | 3867 |
| 3876 | 3868 |
| 3877 } // namespace internal | 3869 } // namespace internal |
| 3878 } // namespace v8 | 3870 } // namespace v8 |
| 3879 | 3871 |
| 3880 #endif // V8_TARGET_ARCH_IA32 | 3872 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |