| 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 |