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_X87 | 5 #if V8_TARGET_ARCH_X87 |
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 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 | 413 |
414 SetReturnPosition(literal()); | 414 SetReturnPosition(literal()); |
415 __ leave(); | 415 __ leave(); |
416 | 416 |
417 int arg_count = info_->scope()->num_parameters() + 1; | 417 int arg_count = info_->scope()->num_parameters() + 1; |
418 int arguments_bytes = arg_count * kPointerSize; | 418 int arguments_bytes = arg_count * kPointerSize; |
419 __ Ret(arguments_bytes, ecx); | 419 __ Ret(arguments_bytes, ecx); |
420 } | 420 } |
421 } | 421 } |
422 | 422 |
| 423 void FullCodeGenerator::RestoreContext() { |
| 424 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 425 } |
423 | 426 |
424 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 427 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
425 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 428 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
426 MemOperand operand = codegen()->VarOperand(var, result_register()); | 429 MemOperand operand = codegen()->VarOperand(var, result_register()); |
427 // Memory operands can be pushed directly. | 430 // Memory operands can be pushed directly. |
428 codegen()->PushOperand(operand); | 431 codegen()->PushOperand(operand); |
429 } | 432 } |
430 | 433 |
431 | 434 |
432 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { | 435 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
(...skipping 899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1332 __ push(Immediate(constant_properties)); | 1335 __ push(Immediate(constant_properties)); |
1333 __ push(Immediate(Smi::FromInt(flags))); | 1336 __ push(Immediate(Smi::FromInt(flags))); |
1334 __ CallRuntime(Runtime::kCreateObjectLiteral); | 1337 __ CallRuntime(Runtime::kCreateObjectLiteral); |
1335 } else { | 1338 } else { |
1336 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1339 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1337 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); | 1340 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); |
1338 __ mov(ecx, Immediate(constant_properties)); | 1341 __ mov(ecx, Immediate(constant_properties)); |
1339 __ mov(edx, Immediate(Smi::FromInt(flags))); | 1342 __ mov(edx, Immediate(Smi::FromInt(flags))); |
1340 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); | 1343 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); |
1341 __ CallStub(&stub); | 1344 __ CallStub(&stub); |
1342 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1345 RestoreContext(); |
1343 } | 1346 } |
1344 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1347 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
1345 | 1348 |
1346 // If result_saved is true the result is on top of the stack. If | 1349 // If result_saved is true the result is on top of the stack. If |
1347 // result_saved is false the result is in eax. | 1350 // result_saved is false the result is in eax. |
1348 bool result_saved = false; | 1351 bool result_saved = false; |
1349 | 1352 |
1350 AccessorTable accessor_table(zone()); | 1353 AccessorTable accessor_table(zone()); |
1351 int property_index = 0; | 1354 int property_index = 0; |
1352 for (; property_index < expr->properties()->length(); property_index++) { | 1355 for (; property_index < expr->properties()->length(); property_index++) { |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1767 Immediate(Smi::FromInt(continuation.pos()))); | 1770 Immediate(Smi::FromInt(continuation.pos()))); |
1768 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); | 1771 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); |
1769 __ mov(ecx, esi); | 1772 __ mov(ecx, esi); |
1770 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, | 1773 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, |
1771 kDontSaveFPRegs); | 1774 kDontSaveFPRegs); |
1772 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); | 1775 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); |
1773 __ cmp(esp, ebx); | 1776 __ cmp(esp, ebx); |
1774 __ j(equal, &post_runtime); | 1777 __ j(equal, &post_runtime); |
1775 __ push(eax); // generator object | 1778 __ push(eax); // generator object |
1776 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1779 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
1777 __ mov(context_register(), | 1780 RestoreContext(); |
1778 Operand(ebp, StandardFrameConstants::kContextOffset)); | |
1779 __ bind(&post_runtime); | 1781 __ bind(&post_runtime); |
1780 PopOperand(result_register()); | 1782 PopOperand(result_register()); |
1781 EmitReturnSequence(); | 1783 EmitReturnSequence(); |
1782 | 1784 |
1783 __ bind(&resume); | 1785 __ bind(&resume); |
1784 context()->Plug(result_register()); | 1786 context()->Plug(result_register()); |
1785 } | 1787 } |
1786 | 1788 |
1787 void FullCodeGenerator::PushOperand(MemOperand operand) { | 1789 void FullCodeGenerator::PushOperand(MemOperand operand) { |
1788 OperandStackDepthIncrement(1); | 1790 OperandStackDepthIncrement(1); |
(...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2409 CodeFactory::CallIC(isolate(), arg_count, mode, expr->tail_call_mode()) | 2411 CodeFactory::CallIC(isolate(), arg_count, mode, expr->tail_call_mode()) |
2410 .code(); | 2412 .code(); |
2411 __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot()))); | 2413 __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot()))); |
2412 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2414 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
2413 // Don't assign a type feedback id to the IC, since type feedback is provided | 2415 // Don't assign a type feedback id to the IC, since type feedback is provided |
2414 // by the vector above. | 2416 // by the vector above. |
2415 CallIC(ic); | 2417 CallIC(ic); |
2416 OperandStackDepthDecrement(arg_count + 1); | 2418 OperandStackDepthDecrement(arg_count + 1); |
2417 | 2419 |
2418 RecordJSReturnSite(expr); | 2420 RecordJSReturnSite(expr); |
2419 | 2421 RestoreContext(); |
2420 // Restore context register. | |
2421 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
2422 | |
2423 context()->DropAndPlug(1, eax); | 2422 context()->DropAndPlug(1, eax); |
2424 } | 2423 } |
2425 | 2424 |
2426 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { | 2425 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { |
2427 int arg_count = expr->arguments()->length(); | 2426 int arg_count = expr->arguments()->length(); |
2428 // Push copy of the first argument or undefined if it doesn't exist. | 2427 // Push copy of the first argument or undefined if it doesn't exist. |
2429 if (arg_count > 0) { | 2428 if (arg_count > 0) { |
2430 __ push(Operand(esp, arg_count * kPointerSize)); | 2429 __ push(Operand(esp, arg_count * kPointerSize)); |
2431 } else { | 2430 } else { |
2432 __ push(Immediate(isolate()->factory()->undefined_value())); | 2431 __ push(Immediate(isolate()->factory()->undefined_value())); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2514 PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS); | 2513 PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS); |
2515 | 2514 |
2516 SetCallPosition(expr); | 2515 SetCallPosition(expr); |
2517 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2516 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
2518 __ Set(eax, arg_count); | 2517 __ Set(eax, arg_count); |
2519 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 2518 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
2520 expr->tail_call_mode()), | 2519 expr->tail_call_mode()), |
2521 RelocInfo::CODE_TARGET); | 2520 RelocInfo::CODE_TARGET); |
2522 OperandStackDepthDecrement(arg_count + 1); | 2521 OperandStackDepthDecrement(arg_count + 1); |
2523 RecordJSReturnSite(expr); | 2522 RecordJSReturnSite(expr); |
2524 // Restore context register. | 2523 RestoreContext(); |
2525 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
2526 context()->DropAndPlug(1, eax); | 2524 context()->DropAndPlug(1, eax); |
2527 } | 2525 } |
2528 | 2526 |
2529 | 2527 |
2530 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2528 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
2531 Comment cmnt(masm_, "[ CallNew"); | 2529 Comment cmnt(masm_, "[ CallNew"); |
2532 // According to ECMA-262, section 11.2.2, page 44, the function | 2530 // According to ECMA-262, section 11.2.2, page 44, the function |
2533 // expression in new calls must be evaluated before the | 2531 // expression in new calls must be evaluated before the |
2534 // arguments. | 2532 // arguments. |
2535 | 2533 |
(...skipping 19 matching lines...) Expand all Loading... |
2555 __ mov(edi, Operand(esp, arg_count * kPointerSize)); | 2553 __ mov(edi, Operand(esp, arg_count * kPointerSize)); |
2556 | 2554 |
2557 // Record call targets in unoptimized code. | 2555 // Record call targets in unoptimized code. |
2558 __ EmitLoadTypeFeedbackVector(ebx); | 2556 __ EmitLoadTypeFeedbackVector(ebx); |
2559 __ mov(edx, Immediate(SmiFromSlot(expr->CallNewFeedbackSlot()))); | 2557 __ mov(edx, Immediate(SmiFromSlot(expr->CallNewFeedbackSlot()))); |
2560 | 2558 |
2561 CallConstructStub stub(isolate()); | 2559 CallConstructStub stub(isolate()); |
2562 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); | 2560 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); |
2563 OperandStackDepthDecrement(arg_count + 1); | 2561 OperandStackDepthDecrement(arg_count + 1); |
2564 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2562 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
2565 // Restore context register. | 2563 RestoreContext(); |
2566 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
2567 context()->Plug(eax); | 2564 context()->Plug(eax); |
2568 } | 2565 } |
2569 | 2566 |
2570 | 2567 |
2571 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { | 2568 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { |
2572 SuperCallReference* super_call_ref = | 2569 SuperCallReference* super_call_ref = |
2573 expr->expression()->AsSuperCallReference(); | 2570 expr->expression()->AsSuperCallReference(); |
2574 DCHECK_NOT_NULL(super_call_ref); | 2571 DCHECK_NOT_NULL(super_call_ref); |
2575 | 2572 |
2576 // Push the super constructor target on the stack (may be null, | 2573 // Push the super constructor target on the stack (may be null, |
(...skipping 20 matching lines...) Expand all Loading... |
2597 __ mov(edx, result_register()); | 2594 __ mov(edx, result_register()); |
2598 | 2595 |
2599 // Load function and argument count into edi and eax. | 2596 // Load function and argument count into edi and eax. |
2600 __ Move(eax, Immediate(arg_count)); | 2597 __ Move(eax, Immediate(arg_count)); |
2601 __ mov(edi, Operand(esp, arg_count * kPointerSize)); | 2598 __ mov(edi, Operand(esp, arg_count * kPointerSize)); |
2602 | 2599 |
2603 __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 2600 __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
2604 OperandStackDepthDecrement(arg_count + 1); | 2601 OperandStackDepthDecrement(arg_count + 1); |
2605 | 2602 |
2606 RecordJSReturnSite(expr); | 2603 RecordJSReturnSite(expr); |
2607 | 2604 RestoreContext(); |
2608 // Restore context register. | |
2609 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
2610 context()->Plug(eax); | 2605 context()->Plug(eax); |
2611 } | 2606 } |
2612 | 2607 |
2613 | 2608 |
2614 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2609 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
2615 ZoneList<Expression*>* args = expr->arguments(); | 2610 ZoneList<Expression*>* args = expr->arguments(); |
2616 DCHECK(args->length() == 1); | 2611 DCHECK(args->length() == 1); |
2617 | 2612 |
2618 VisitForAccumulatorValue(args->at(0)); | 2613 VisitForAccumulatorValue(args->at(0)); |
2619 | 2614 |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3000 VisitForStackValue(arg); | 2995 VisitForStackValue(arg); |
3001 } | 2996 } |
3002 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); | 2997 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); |
3003 // Move target to edi. | 2998 // Move target to edi. |
3004 int const argc = args->length() - 2; | 2999 int const argc = args->length() - 2; |
3005 __ mov(edi, Operand(esp, (argc + 1) * kPointerSize)); | 3000 __ mov(edi, Operand(esp, (argc + 1) * kPointerSize)); |
3006 // Call the target. | 3001 // Call the target. |
3007 __ mov(eax, Immediate(argc)); | 3002 __ mov(eax, Immediate(argc)); |
3008 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 3003 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
3009 OperandStackDepthDecrement(argc + 1); | 3004 OperandStackDepthDecrement(argc + 1); |
3010 // Restore context register. | 3005 RestoreContext(); |
3011 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
3012 // Discard the function left on TOS. | 3006 // Discard the function left on TOS. |
3013 context()->DropAndPlug(1, eax); | 3007 context()->DropAndPlug(1, eax); |
3014 } | 3008 } |
3015 | 3009 |
3016 | 3010 |
3017 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3011 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
3018 ZoneList<Expression*>* args = expr->arguments(); | 3012 ZoneList<Expression*>* args = expr->arguments(); |
3019 DCHECK(args->length() == 1); | 3013 DCHECK(args->length() == 1); |
3020 | 3014 |
3021 VisitForAccumulatorValue(args->at(0)); | 3015 VisitForAccumulatorValue(args->at(0)); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3121 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { | 3115 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { |
3122 ZoneList<Expression*>* args = expr->arguments(); | 3116 ZoneList<Expression*>* args = expr->arguments(); |
3123 int arg_count = args->length(); | 3117 int arg_count = args->length(); |
3124 | 3118 |
3125 SetCallPosition(expr); | 3119 SetCallPosition(expr); |
3126 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 3120 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
3127 __ Set(eax, arg_count); | 3121 __ Set(eax, arg_count); |
3128 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), | 3122 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), |
3129 RelocInfo::CODE_TARGET); | 3123 RelocInfo::CODE_TARGET); |
3130 OperandStackDepthDecrement(arg_count + 1); | 3124 OperandStackDepthDecrement(arg_count + 1); |
3131 | 3125 RestoreContext(); |
3132 // Restore context register. | |
3133 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
3134 } | 3126 } |
3135 | 3127 |
3136 | 3128 |
3137 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3129 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
3138 switch (expr->op()) { | 3130 switch (expr->op()) { |
3139 case Token::DELETE: { | 3131 case Token::DELETE: { |
3140 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3132 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
3141 Property* property = expr->expression()->AsProperty(); | 3133 Property* property = expr->expression()->AsProperty(); |
3142 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 3134 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
3143 | 3135 |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3597 Label* fall_through = NULL; | 3589 Label* fall_through = NULL; |
3598 context()->PrepareTest(&materialize_true, &materialize_false, | 3590 context()->PrepareTest(&materialize_true, &materialize_false, |
3599 &if_true, &if_false, &fall_through); | 3591 &if_true, &if_false, &fall_through); |
3600 | 3592 |
3601 Token::Value op = expr->op(); | 3593 Token::Value op = expr->op(); |
3602 VisitForStackValue(expr->left()); | 3594 VisitForStackValue(expr->left()); |
3603 switch (op) { | 3595 switch (op) { |
3604 case Token::IN: | 3596 case Token::IN: |
3605 VisitForStackValue(expr->right()); | 3597 VisitForStackValue(expr->right()); |
3606 SetExpressionPosition(expr); | 3598 SetExpressionPosition(expr); |
3607 CallRuntimeWithOperands(Runtime::kHasProperty); | 3599 EmitHasProperty(); |
3608 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); | 3600 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
3609 __ cmp(eax, isolate()->factory()->true_value()); | 3601 __ cmp(eax, isolate()->factory()->true_value()); |
3610 Split(equal, if_true, if_false, fall_through); | 3602 Split(equal, if_true, if_false, fall_through); |
3611 break; | 3603 break; |
3612 | 3604 |
3613 case Token::INSTANCEOF: { | 3605 case Token::INSTANCEOF: { |
3614 VisitForAccumulatorValue(expr->right()); | 3606 VisitForAccumulatorValue(expr->right()); |
3615 SetExpressionPosition(expr); | 3607 SetExpressionPosition(expr); |
3616 PopOperand(edx); | 3608 PopOperand(edx); |
3617 InstanceOfStub stub(isolate()); | 3609 InstanceOfStub stub(isolate()); |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3863 isolate->builtins()->OnStackReplacement()->entry(), | 3855 isolate->builtins()->OnStackReplacement()->entry(), |
3864 Assembler::target_address_at(call_target_address, unoptimized_code)); | 3856 Assembler::target_address_at(call_target_address, unoptimized_code)); |
3865 return ON_STACK_REPLACEMENT; | 3857 return ON_STACK_REPLACEMENT; |
3866 } | 3858 } |
3867 | 3859 |
3868 | 3860 |
3869 } // namespace internal | 3861 } // namespace internal |
3870 } // namespace v8 | 3862 } // namespace v8 |
3871 | 3863 |
3872 #endif // V8_TARGET_ARCH_X87 | 3864 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |