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 |