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_ARM | 5 #if V8_TARGET_ARCH_ARM |
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 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 PredictableCodeSizeScope predictable(masm_, -1); | 461 PredictableCodeSizeScope predictable(masm_, -1); |
462 __ LeaveFrame(StackFrame::JAVA_SCRIPT); | 462 __ LeaveFrame(StackFrame::JAVA_SCRIPT); |
463 { ConstantPoolUnavailableScope constant_pool_unavailable(masm_); | 463 { ConstantPoolUnavailableScope constant_pool_unavailable(masm_); |
464 __ add(sp, sp, Operand(sp_delta)); | 464 __ add(sp, sp, Operand(sp_delta)); |
465 __ Jump(lr); | 465 __ Jump(lr); |
466 } | 466 } |
467 } | 467 } |
468 } | 468 } |
469 } | 469 } |
470 | 470 |
| 471 void FullCodeGenerator::RestoreContext() { |
| 472 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 473 } |
471 | 474 |
472 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 475 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
473 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 476 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
474 codegen()->GetVar(result_register(), var); | 477 codegen()->GetVar(result_register(), var); |
475 codegen()->PushOperand(result_register()); | 478 codegen()->PushOperand(result_register()); |
476 } | 479 } |
477 | 480 |
478 | 481 |
479 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { | 482 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
480 } | 483 } |
(...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1411 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); | 1414 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); |
1412 __ mov(r1, Operand(constant_properties)); | 1415 __ mov(r1, Operand(constant_properties)); |
1413 int flags = expr->ComputeFlags(); | 1416 int flags = expr->ComputeFlags(); |
1414 __ mov(r0, Operand(Smi::FromInt(flags))); | 1417 __ mov(r0, Operand(Smi::FromInt(flags))); |
1415 if (MustCreateObjectLiteralWithRuntime(expr)) { | 1418 if (MustCreateObjectLiteralWithRuntime(expr)) { |
1416 __ Push(r3, r2, r1, r0); | 1419 __ Push(r3, r2, r1, r0); |
1417 __ CallRuntime(Runtime::kCreateObjectLiteral); | 1420 __ CallRuntime(Runtime::kCreateObjectLiteral); |
1418 } else { | 1421 } else { |
1419 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); | 1422 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); |
1420 __ CallStub(&stub); | 1423 __ CallStub(&stub); |
1421 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1424 RestoreContext(); |
1422 } | 1425 } |
1423 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1426 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
1424 | 1427 |
1425 // If result_saved is true the result is on top of the stack. If | 1428 // If result_saved is true the result is on top of the stack. If |
1426 // result_saved is false the result is in r0. | 1429 // result_saved is false the result is in r0. |
1427 bool result_saved = false; | 1430 bool result_saved = false; |
1428 | 1431 |
1429 AccessorTable accessor_table(zone()); | 1432 AccessorTable accessor_table(zone()); |
1430 int property_index = 0; | 1433 int property_index = 0; |
1431 for (; property_index < expr->properties()->length(); property_index++) { | 1434 for (; property_index < expr->properties()->length(); property_index++) { |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1859 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); | 1862 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); |
1860 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); | 1863 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); |
1861 __ mov(r1, cp); | 1864 __ mov(r1, cp); |
1862 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, | 1865 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, |
1863 kLRHasBeenSaved, kDontSaveFPRegs); | 1866 kLRHasBeenSaved, kDontSaveFPRegs); |
1864 __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); | 1867 __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); |
1865 __ cmp(sp, r1); | 1868 __ cmp(sp, r1); |
1866 __ b(eq, &post_runtime); | 1869 __ b(eq, &post_runtime); |
1867 __ push(r0); // generator object | 1870 __ push(r0); // generator object |
1868 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1871 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
1869 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1872 RestoreContext(); |
1870 __ bind(&post_runtime); | 1873 __ bind(&post_runtime); |
1871 PopOperand(result_register()); | 1874 PopOperand(result_register()); |
1872 EmitReturnSequence(); | 1875 EmitReturnSequence(); |
1873 | 1876 |
1874 __ bind(&resume); | 1877 __ bind(&resume); |
1875 context()->Plug(result_register()); | 1878 context()->Plug(result_register()); |
1876 } | 1879 } |
1877 | 1880 |
1878 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) { | 1881 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) { |
1879 OperandStackDepthIncrement(2); | 1882 OperandStackDepthIncrement(2); |
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2520 CodeFactory::CallIC(isolate(), arg_count, mode, expr->tail_call_mode()) | 2523 CodeFactory::CallIC(isolate(), arg_count, mode, expr->tail_call_mode()) |
2521 .code(); | 2524 .code(); |
2522 __ mov(r3, Operand(SmiFromSlot(expr->CallFeedbackICSlot()))); | 2525 __ mov(r3, Operand(SmiFromSlot(expr->CallFeedbackICSlot()))); |
2523 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2526 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
2524 // Don't assign a type feedback id to the IC, since type feedback is provided | 2527 // Don't assign a type feedback id to the IC, since type feedback is provided |
2525 // by the vector above. | 2528 // by the vector above. |
2526 CallIC(ic); | 2529 CallIC(ic); |
2527 OperandStackDepthDecrement(arg_count + 1); | 2530 OperandStackDepthDecrement(arg_count + 1); |
2528 | 2531 |
2529 RecordJSReturnSite(expr); | 2532 RecordJSReturnSite(expr); |
2530 // Restore context register. | 2533 RestoreContext(); |
2531 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
2532 context()->DropAndPlug(1, r0); | 2534 context()->DropAndPlug(1, r0); |
2533 } | 2535 } |
2534 | 2536 |
2535 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { | 2537 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { |
2536 int arg_count = expr->arguments()->length(); | 2538 int arg_count = expr->arguments()->length(); |
2537 // r4: copy of the first argument or undefined if it doesn't exist. | 2539 // r4: copy of the first argument or undefined if it doesn't exist. |
2538 if (arg_count > 0) { | 2540 if (arg_count > 0) { |
2539 __ ldr(r4, MemOperand(sp, arg_count * kPointerSize)); | 2541 __ ldr(r4, MemOperand(sp, arg_count * kPointerSize)); |
2540 } else { | 2542 } else { |
2541 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); | 2543 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2628 | 2630 |
2629 // Record source position for debugger. | 2631 // Record source position for debugger. |
2630 SetCallPosition(expr); | 2632 SetCallPosition(expr); |
2631 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2633 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
2632 __ mov(r0, Operand(arg_count)); | 2634 __ mov(r0, Operand(arg_count)); |
2633 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 2635 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
2634 expr->tail_call_mode()), | 2636 expr->tail_call_mode()), |
2635 RelocInfo::CODE_TARGET); | 2637 RelocInfo::CODE_TARGET); |
2636 OperandStackDepthDecrement(arg_count + 1); | 2638 OperandStackDepthDecrement(arg_count + 1); |
2637 RecordJSReturnSite(expr); | 2639 RecordJSReturnSite(expr); |
2638 // Restore context register. | 2640 RestoreContext(); |
2639 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
2640 context()->DropAndPlug(1, r0); | 2641 context()->DropAndPlug(1, r0); |
2641 } | 2642 } |
2642 | 2643 |
2643 | 2644 |
2644 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2645 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
2645 Comment cmnt(masm_, "[ CallNew"); | 2646 Comment cmnt(masm_, "[ CallNew"); |
2646 // According to ECMA-262, section 11.2.2, page 44, the function | 2647 // According to ECMA-262, section 11.2.2, page 44, the function |
2647 // expression in new calls must be evaluated before the | 2648 // expression in new calls must be evaluated before the |
2648 // arguments. | 2649 // arguments. |
2649 | 2650 |
(...skipping 19 matching lines...) Expand all Loading... |
2669 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); | 2670 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); |
2670 | 2671 |
2671 // Record call targets in unoptimized code. | 2672 // Record call targets in unoptimized code. |
2672 __ EmitLoadTypeFeedbackVector(r2); | 2673 __ EmitLoadTypeFeedbackVector(r2); |
2673 __ mov(r3, Operand(SmiFromSlot(expr->CallNewFeedbackSlot()))); | 2674 __ mov(r3, Operand(SmiFromSlot(expr->CallNewFeedbackSlot()))); |
2674 | 2675 |
2675 CallConstructStub stub(isolate()); | 2676 CallConstructStub stub(isolate()); |
2676 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET); | 2677 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET); |
2677 OperandStackDepthDecrement(arg_count + 1); | 2678 OperandStackDepthDecrement(arg_count + 1); |
2678 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2679 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
2679 // Restore context register. | 2680 RestoreContext(); |
2680 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
2681 context()->Plug(r0); | 2681 context()->Plug(r0); |
2682 } | 2682 } |
2683 | 2683 |
2684 | 2684 |
2685 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { | 2685 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { |
2686 SuperCallReference* super_call_ref = | 2686 SuperCallReference* super_call_ref = |
2687 expr->expression()->AsSuperCallReference(); | 2687 expr->expression()->AsSuperCallReference(); |
2688 DCHECK_NOT_NULL(super_call_ref); | 2688 DCHECK_NOT_NULL(super_call_ref); |
2689 | 2689 |
2690 // Push the super constructor target on the stack (may be null, | 2690 // Push the super constructor target on the stack (may be null, |
(...skipping 22 matching lines...) Expand all Loading... |
2713 __ mov(r3, result_register()); | 2713 __ mov(r3, result_register()); |
2714 | 2714 |
2715 // Load function and argument count into r1 and r0. | 2715 // Load function and argument count into r1 and r0. |
2716 __ mov(r0, Operand(arg_count)); | 2716 __ mov(r0, Operand(arg_count)); |
2717 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); | 2717 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); |
2718 | 2718 |
2719 __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 2719 __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
2720 OperandStackDepthDecrement(arg_count + 1); | 2720 OperandStackDepthDecrement(arg_count + 1); |
2721 | 2721 |
2722 RecordJSReturnSite(expr); | 2722 RecordJSReturnSite(expr); |
2723 | 2723 RestoreContext(); |
2724 // Restore context register. | |
2725 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
2726 context()->Plug(r0); | 2724 context()->Plug(r0); |
2727 } | 2725 } |
2728 | 2726 |
2729 | 2727 |
2730 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2728 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
2731 ZoneList<Expression*>* args = expr->arguments(); | 2729 ZoneList<Expression*>* args = expr->arguments(); |
2732 DCHECK(args->length() == 1); | 2730 DCHECK(args->length() == 1); |
2733 | 2731 |
2734 VisitForAccumulatorValue(args->at(0)); | 2732 VisitForAccumulatorValue(args->at(0)); |
2735 | 2733 |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3111 VisitForStackValue(arg); | 3109 VisitForStackValue(arg); |
3112 } | 3110 } |
3113 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); | 3111 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); |
3114 // Move target to r1. | 3112 // Move target to r1. |
3115 int const argc = args->length() - 2; | 3113 int const argc = args->length() - 2; |
3116 __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize)); | 3114 __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize)); |
3117 // Call the target. | 3115 // Call the target. |
3118 __ mov(r0, Operand(argc)); | 3116 __ mov(r0, Operand(argc)); |
3119 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 3117 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
3120 OperandStackDepthDecrement(argc + 1); | 3118 OperandStackDepthDecrement(argc + 1); |
3121 // Restore context register. | 3119 RestoreContext(); |
3122 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
3123 // Discard the function left on TOS. | 3120 // Discard the function left on TOS. |
3124 context()->DropAndPlug(1, r0); | 3121 context()->DropAndPlug(1, r0); |
3125 } | 3122 } |
3126 | 3123 |
3127 | 3124 |
3128 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3125 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
3129 ZoneList<Expression*>* args = expr->arguments(); | 3126 ZoneList<Expression*>* args = expr->arguments(); |
3130 VisitForAccumulatorValue(args->at(0)); | 3127 VisitForAccumulatorValue(args->at(0)); |
3131 | 3128 |
3132 Label materialize_true, materialize_false; | 3129 Label materialize_true, materialize_false; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3229 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { | 3226 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { |
3230 ZoneList<Expression*>* args = expr->arguments(); | 3227 ZoneList<Expression*>* args = expr->arguments(); |
3231 int arg_count = args->length(); | 3228 int arg_count = args->length(); |
3232 | 3229 |
3233 SetCallPosition(expr); | 3230 SetCallPosition(expr); |
3234 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 3231 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
3235 __ mov(r0, Operand(arg_count)); | 3232 __ mov(r0, Operand(arg_count)); |
3236 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), | 3233 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), |
3237 RelocInfo::CODE_TARGET); | 3234 RelocInfo::CODE_TARGET); |
3238 OperandStackDepthDecrement(arg_count + 1); | 3235 OperandStackDepthDecrement(arg_count + 1); |
3239 | 3236 RestoreContext(); |
3240 // Restore context register. | |
3241 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
3242 } | 3237 } |
3243 | 3238 |
3244 | 3239 |
3245 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3240 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
3246 switch (expr->op()) { | 3241 switch (expr->op()) { |
3247 case Token::DELETE: { | 3242 case Token::DELETE: { |
3248 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3243 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
3249 Property* property = expr->expression()->AsProperty(); | 3244 Property* property = expr->expression()->AsProperty(); |
3250 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 3245 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
3251 | 3246 |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3697 Label* fall_through = NULL; | 3692 Label* fall_through = NULL; |
3698 context()->PrepareTest(&materialize_true, &materialize_false, | 3693 context()->PrepareTest(&materialize_true, &materialize_false, |
3699 &if_true, &if_false, &fall_through); | 3694 &if_true, &if_false, &fall_through); |
3700 | 3695 |
3701 Token::Value op = expr->op(); | 3696 Token::Value op = expr->op(); |
3702 VisitForStackValue(expr->left()); | 3697 VisitForStackValue(expr->left()); |
3703 switch (op) { | 3698 switch (op) { |
3704 case Token::IN: | 3699 case Token::IN: |
3705 VisitForStackValue(expr->right()); | 3700 VisitForStackValue(expr->right()); |
3706 SetExpressionPosition(expr); | 3701 SetExpressionPosition(expr); |
3707 CallRuntimeWithOperands(Runtime::kHasProperty); | 3702 EmitHasProperty(); |
3708 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); | 3703 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
3709 __ CompareRoot(r0, Heap::kTrueValueRootIndex); | 3704 __ CompareRoot(r0, Heap::kTrueValueRootIndex); |
3710 Split(eq, if_true, if_false, fall_through); | 3705 Split(eq, if_true, if_false, fall_through); |
3711 break; | 3706 break; |
3712 | 3707 |
3713 case Token::INSTANCEOF: { | 3708 case Token::INSTANCEOF: { |
3714 VisitForAccumulatorValue(expr->right()); | 3709 VisitForAccumulatorValue(expr->right()); |
3715 SetExpressionPosition(expr); | 3710 SetExpressionPosition(expr); |
3716 PopOperand(r1); | 3711 PopOperand(r1); |
3717 InstanceOfStub stub(isolate()); | 3712 InstanceOfStub stub(isolate()); |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4030 DCHECK(interrupt_address == | 4025 DCHECK(interrupt_address == |
4031 isolate->builtins()->OnStackReplacement()->entry()); | 4026 isolate->builtins()->OnStackReplacement()->entry()); |
4032 return ON_STACK_REPLACEMENT; | 4027 return ON_STACK_REPLACEMENT; |
4033 } | 4028 } |
4034 | 4029 |
4035 | 4030 |
4036 } // namespace internal | 4031 } // namespace internal |
4037 } // namespace v8 | 4032 } // namespace v8 |
4038 | 4033 |
4039 #endif // V8_TARGET_ARCH_ARM | 4034 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |