| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
| 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 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 // arguments, consider how to improve it without creating a security | 453 // arguments, consider how to improve it without creating a security |
| 454 // hole. | 454 // hole. |
| 455 __ ldr_pcrel(ip0, (3 * kInstructionSize) >> kLoadLiteralScaleLog2); | 455 __ ldr_pcrel(ip0, (3 * kInstructionSize) >> kLoadLiteralScaleLog2); |
| 456 __ Add(current_sp, current_sp, ip0); | 456 __ Add(current_sp, current_sp, ip0); |
| 457 __ Ret(); | 457 __ Ret(); |
| 458 int32_t arg_count = info_->scope()->num_parameters() + 1; | 458 int32_t arg_count = info_->scope()->num_parameters() + 1; |
| 459 __ dc64(kXRegSize * arg_count); | 459 __ dc64(kXRegSize * arg_count); |
| 460 } | 460 } |
| 461 } | 461 } |
| 462 | 462 |
| 463 void FullCodeGenerator::RestoreContext() { |
| 464 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 465 } |
| 463 | 466 |
| 464 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 467 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
| 465 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 468 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 466 codegen()->GetVar(result_register(), var); | 469 codegen()->GetVar(result_register(), var); |
| 467 codegen()->PushOperand(result_register()); | 470 codegen()->PushOperand(result_register()); |
| 468 } | 471 } |
| 469 | 472 |
| 470 | 473 |
| 471 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { | 474 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
| 472 // Root values have no side effects. | 475 // Root values have no side effects. |
| (...skipping 924 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1397 __ Mov(x2, Smi::FromInt(expr->literal_index())); | 1400 __ Mov(x2, Smi::FromInt(expr->literal_index())); |
| 1398 __ Mov(x1, Operand(constant_properties)); | 1401 __ Mov(x1, Operand(constant_properties)); |
| 1399 int flags = expr->ComputeFlags(); | 1402 int flags = expr->ComputeFlags(); |
| 1400 __ Mov(x0, Smi::FromInt(flags)); | 1403 __ Mov(x0, Smi::FromInt(flags)); |
| 1401 if (MustCreateObjectLiteralWithRuntime(expr)) { | 1404 if (MustCreateObjectLiteralWithRuntime(expr)) { |
| 1402 __ Push(x3, x2, x1, x0); | 1405 __ Push(x3, x2, x1, x0); |
| 1403 __ CallRuntime(Runtime::kCreateObjectLiteral); | 1406 __ CallRuntime(Runtime::kCreateObjectLiteral); |
| 1404 } else { | 1407 } else { |
| 1405 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); | 1408 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); |
| 1406 __ CallStub(&stub); | 1409 __ CallStub(&stub); |
| 1407 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1410 RestoreContext(); |
| 1408 } | 1411 } |
| 1409 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1412 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
| 1410 | 1413 |
| 1411 // If result_saved is true the result is on top of the stack. If | 1414 // If result_saved is true the result is on top of the stack. If |
| 1412 // result_saved is false the result is in x0. | 1415 // result_saved is false the result is in x0. |
| 1413 bool result_saved = false; | 1416 bool result_saved = false; |
| 1414 | 1417 |
| 1415 AccessorTable accessor_table(zone()); | 1418 AccessorTable accessor_table(zone()); |
| 1416 int property_index = 0; | 1419 int property_index = 0; |
| 1417 for (; property_index < expr->properties()->length(); property_index++) { | 1420 for (; property_index < expr->properties()->length(); property_index++) { |
| (...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2421 CodeFactory::CallIC(isolate(), arg_count, mode, expr->tail_call_mode()) | 2424 CodeFactory::CallIC(isolate(), arg_count, mode, expr->tail_call_mode()) |
| 2422 .code(); | 2425 .code(); |
| 2423 __ Mov(x3, SmiFromSlot(expr->CallFeedbackICSlot())); | 2426 __ Mov(x3, SmiFromSlot(expr->CallFeedbackICSlot())); |
| 2424 __ Peek(x1, (arg_count + 1) * kXRegSize); | 2427 __ Peek(x1, (arg_count + 1) * kXRegSize); |
| 2425 // Don't assign a type feedback id to the IC, since type feedback is provided | 2428 // Don't assign a type feedback id to the IC, since type feedback is provided |
| 2426 // by the vector above. | 2429 // by the vector above. |
| 2427 CallIC(ic); | 2430 CallIC(ic); |
| 2428 OperandStackDepthDecrement(arg_count + 1); | 2431 OperandStackDepthDecrement(arg_count + 1); |
| 2429 | 2432 |
| 2430 RecordJSReturnSite(expr); | 2433 RecordJSReturnSite(expr); |
| 2431 // Restore context register. | 2434 RestoreContext(); |
| 2432 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 2433 context()->DropAndPlug(1, x0); | 2435 context()->DropAndPlug(1, x0); |
| 2434 } | 2436 } |
| 2435 | 2437 |
| 2436 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { | 2438 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { |
| 2437 int arg_count = expr->arguments()->length(); | 2439 int arg_count = expr->arguments()->length(); |
| 2438 ASM_LOCATION("FullCodeGenerator::EmitResolvePossiblyDirectEval"); | 2440 ASM_LOCATION("FullCodeGenerator::EmitResolvePossiblyDirectEval"); |
| 2439 // Prepare to push a copy of the first argument or undefined if it doesn't | 2441 // Prepare to push a copy of the first argument or undefined if it doesn't |
| 2440 // exist. | 2442 // exist. |
| 2441 if (arg_count > 0) { | 2443 if (arg_count > 0) { |
| 2442 __ Peek(x9, arg_count * kXRegSize); | 2444 __ Peek(x9, arg_count * kXRegSize); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2532 SetCallPosition(expr); | 2534 SetCallPosition(expr); |
| 2533 | 2535 |
| 2534 // Call the evaluated function. | 2536 // Call the evaluated function. |
| 2535 __ Peek(x1, (arg_count + 1) * kXRegSize); | 2537 __ Peek(x1, (arg_count + 1) * kXRegSize); |
| 2536 __ Mov(x0, arg_count); | 2538 __ Mov(x0, arg_count); |
| 2537 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 2539 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
| 2538 expr->tail_call_mode()), | 2540 expr->tail_call_mode()), |
| 2539 RelocInfo::CODE_TARGET); | 2541 RelocInfo::CODE_TARGET); |
| 2540 OperandStackDepthDecrement(arg_count + 1); | 2542 OperandStackDepthDecrement(arg_count + 1); |
| 2541 RecordJSReturnSite(expr); | 2543 RecordJSReturnSite(expr); |
| 2542 // Restore context register. | 2544 RestoreContext(); |
| 2543 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 2544 context()->DropAndPlug(1, x0); | 2545 context()->DropAndPlug(1, x0); |
| 2545 } | 2546 } |
| 2546 | 2547 |
| 2547 | 2548 |
| 2548 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2549 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
| 2549 Comment cmnt(masm_, "[ CallNew"); | 2550 Comment cmnt(masm_, "[ CallNew"); |
| 2550 // According to ECMA-262, section 11.2.2, page 44, the function | 2551 // According to ECMA-262, section 11.2.2, page 44, the function |
| 2551 // expression in new calls must be evaluated before the | 2552 // expression in new calls must be evaluated before the |
| 2552 // arguments. | 2553 // arguments. |
| 2553 | 2554 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2573 __ Peek(x1, arg_count * kXRegSize); | 2574 __ Peek(x1, arg_count * kXRegSize); |
| 2574 | 2575 |
| 2575 // Record call targets in unoptimized code. | 2576 // Record call targets in unoptimized code. |
| 2576 __ EmitLoadTypeFeedbackVector(x2); | 2577 __ EmitLoadTypeFeedbackVector(x2); |
| 2577 __ Mov(x3, SmiFromSlot(expr->CallNewFeedbackSlot())); | 2578 __ Mov(x3, SmiFromSlot(expr->CallNewFeedbackSlot())); |
| 2578 | 2579 |
| 2579 CallConstructStub stub(isolate()); | 2580 CallConstructStub stub(isolate()); |
| 2580 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET); | 2581 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 2581 OperandStackDepthDecrement(arg_count + 1); | 2582 OperandStackDepthDecrement(arg_count + 1); |
| 2582 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2583 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
| 2583 // Restore context register. | 2584 RestoreContext(); |
| 2584 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 2585 context()->Plug(x0); | 2585 context()->Plug(x0); |
| 2586 } | 2586 } |
| 2587 | 2587 |
| 2588 | 2588 |
| 2589 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { | 2589 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { |
| 2590 ASM_LOCATION("FullCodeGenerator::EmitSuperConstructorCall"); | 2590 ASM_LOCATION("FullCodeGenerator::EmitSuperConstructorCall"); |
| 2591 SuperCallReference* super_call_ref = | 2591 SuperCallReference* super_call_ref = |
| 2592 expr->expression()->AsSuperCallReference(); | 2592 expr->expression()->AsSuperCallReference(); |
| 2593 DCHECK_NOT_NULL(super_call_ref); | 2593 DCHECK_NOT_NULL(super_call_ref); |
| 2594 | 2594 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2618 __ Mov(x3, result_register()); | 2618 __ Mov(x3, result_register()); |
| 2619 | 2619 |
| 2620 // Load function and argument count into x1 and x0. | 2620 // Load function and argument count into x1 and x0. |
| 2621 __ Mov(x0, arg_count); | 2621 __ Mov(x0, arg_count); |
| 2622 __ Peek(x1, arg_count * kXRegSize); | 2622 __ Peek(x1, arg_count * kXRegSize); |
| 2623 | 2623 |
| 2624 __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 2624 __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 2625 OperandStackDepthDecrement(arg_count + 1); | 2625 OperandStackDepthDecrement(arg_count + 1); |
| 2626 | 2626 |
| 2627 RecordJSReturnSite(expr); | 2627 RecordJSReturnSite(expr); |
| 2628 | 2628 RestoreContext(); |
| 2629 // Restore context register. | |
| 2630 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 2631 context()->Plug(x0); | 2629 context()->Plug(x0); |
| 2632 } | 2630 } |
| 2633 | 2631 |
| 2634 | 2632 |
| 2635 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2633 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
| 2636 ZoneList<Expression*>* args = expr->arguments(); | 2634 ZoneList<Expression*>* args = expr->arguments(); |
| 2637 DCHECK(args->length() == 1); | 2635 DCHECK(args->length() == 1); |
| 2638 | 2636 |
| 2639 VisitForAccumulatorValue(args->at(0)); | 2637 VisitForAccumulatorValue(args->at(0)); |
| 2640 | 2638 |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3016 VisitForStackValue(arg); | 3014 VisitForStackValue(arg); |
| 3017 } | 3015 } |
| 3018 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); | 3016 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); |
| 3019 // Move target to x1. | 3017 // Move target to x1. |
| 3020 int const argc = args->length() - 2; | 3018 int const argc = args->length() - 2; |
| 3021 __ Peek(x1, (argc + 1) * kXRegSize); | 3019 __ Peek(x1, (argc + 1) * kXRegSize); |
| 3022 // Call the target. | 3020 // Call the target. |
| 3023 __ Mov(x0, argc); | 3021 __ Mov(x0, argc); |
| 3024 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 3022 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 3025 OperandStackDepthDecrement(argc + 1); | 3023 OperandStackDepthDecrement(argc + 1); |
| 3026 // Restore context register. | 3024 RestoreContext(); |
| 3027 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 3028 // Discard the function left on TOS. | 3025 // Discard the function left on TOS. |
| 3029 context()->DropAndPlug(1, x0); | 3026 context()->DropAndPlug(1, x0); |
| 3030 } | 3027 } |
| 3031 | 3028 |
| 3032 | 3029 |
| 3033 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3030 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
| 3034 ZoneList<Expression*>* args = expr->arguments(); | 3031 ZoneList<Expression*>* args = expr->arguments(); |
| 3035 VisitForAccumulatorValue(args->at(0)); | 3032 VisitForAccumulatorValue(args->at(0)); |
| 3036 | 3033 |
| 3037 Label materialize_true, materialize_false; | 3034 Label materialize_true, materialize_false; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3145 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { | 3142 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { |
| 3146 ZoneList<Expression*>* args = expr->arguments(); | 3143 ZoneList<Expression*>* args = expr->arguments(); |
| 3147 int arg_count = args->length(); | 3144 int arg_count = args->length(); |
| 3148 | 3145 |
| 3149 SetCallPosition(expr); | 3146 SetCallPosition(expr); |
| 3150 __ Peek(x1, (arg_count + 1) * kPointerSize); | 3147 __ Peek(x1, (arg_count + 1) * kPointerSize); |
| 3151 __ Mov(x0, arg_count); | 3148 __ Mov(x0, arg_count); |
| 3152 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), | 3149 __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), |
| 3153 RelocInfo::CODE_TARGET); | 3150 RelocInfo::CODE_TARGET); |
| 3154 OperandStackDepthDecrement(arg_count + 1); | 3151 OperandStackDepthDecrement(arg_count + 1); |
| 3155 | 3152 RestoreContext(); |
| 3156 // Restore context register. | |
| 3157 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 3158 } | 3153 } |
| 3159 | 3154 |
| 3160 | 3155 |
| 3161 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3156 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 3162 switch (expr->op()) { | 3157 switch (expr->op()) { |
| 3163 case Token::DELETE: { | 3158 case Token::DELETE: { |
| 3164 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3159 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 3165 Property* property = expr->expression()->AsProperty(); | 3160 Property* property = expr->expression()->AsProperty(); |
| 3166 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 3161 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 3167 | 3162 |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3620 Label* fall_through = NULL; | 3615 Label* fall_through = NULL; |
| 3621 context()->PrepareTest(&materialize_true, &materialize_false, | 3616 context()->PrepareTest(&materialize_true, &materialize_false, |
| 3622 &if_true, &if_false, &fall_through); | 3617 &if_true, &if_false, &fall_through); |
| 3623 | 3618 |
| 3624 Token::Value op = expr->op(); | 3619 Token::Value op = expr->op(); |
| 3625 VisitForStackValue(expr->left()); | 3620 VisitForStackValue(expr->left()); |
| 3626 switch (op) { | 3621 switch (op) { |
| 3627 case Token::IN: | 3622 case Token::IN: |
| 3628 VisitForStackValue(expr->right()); | 3623 VisitForStackValue(expr->right()); |
| 3629 SetExpressionPosition(expr); | 3624 SetExpressionPosition(expr); |
| 3630 CallRuntimeWithOperands(Runtime::kHasProperty); | 3625 EmitHasProperty(); |
| 3631 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); | 3626 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
| 3632 __ CompareRoot(x0, Heap::kTrueValueRootIndex); | 3627 __ CompareRoot(x0, Heap::kTrueValueRootIndex); |
| 3633 Split(eq, if_true, if_false, fall_through); | 3628 Split(eq, if_true, if_false, fall_through); |
| 3634 break; | 3629 break; |
| 3635 | 3630 |
| 3636 case Token::INSTANCEOF: { | 3631 case Token::INSTANCEOF: { |
| 3637 VisitForAccumulatorValue(expr->right()); | 3632 VisitForAccumulatorValue(expr->right()); |
| 3638 SetExpressionPosition(expr); | 3633 SetExpressionPosition(expr); |
| 3639 PopOperand(x1); | 3634 PopOperand(x1); |
| 3640 InstanceOfStub stub(isolate()); | 3635 InstanceOfStub stub(isolate()); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3751 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); | 3746 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); |
| 3752 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); | 3747 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); |
| 3753 __ Mov(x1, cp); | 3748 __ Mov(x1, cp); |
| 3754 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, | 3749 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, |
| 3755 kLRHasBeenSaved, kDontSaveFPRegs); | 3750 kLRHasBeenSaved, kDontSaveFPRegs); |
| 3756 __ Add(x1, fp, StandardFrameConstants::kExpressionsOffset); | 3751 __ Add(x1, fp, StandardFrameConstants::kExpressionsOffset); |
| 3757 __ Cmp(__ StackPointer(), x1); | 3752 __ Cmp(__ StackPointer(), x1); |
| 3758 __ B(eq, &post_runtime); | 3753 __ B(eq, &post_runtime); |
| 3759 __ Push(x0); // generator object | 3754 __ Push(x0); // generator object |
| 3760 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 3755 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 3761 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3756 RestoreContext(); |
| 3762 __ Bind(&post_runtime); | 3757 __ Bind(&post_runtime); |
| 3763 PopOperand(result_register()); | 3758 PopOperand(result_register()); |
| 3764 EmitReturnSequence(); | 3759 EmitReturnSequence(); |
| 3765 | 3760 |
| 3766 __ Bind(&resume); | 3761 __ Bind(&resume); |
| 3767 context()->Plug(result_register()); | 3762 context()->Plug(result_register()); |
| 3768 } | 3763 } |
| 3769 | 3764 |
| 3770 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) { | 3765 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) { |
| 3771 OperandStackDepthIncrement(2); | 3766 OperandStackDepthIncrement(2); |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4030 } | 4025 } |
| 4031 | 4026 |
| 4032 return INTERRUPT; | 4027 return INTERRUPT; |
| 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_ARM64 | 4034 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |