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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 | 465 |
466 int arg_count = info_->scope()->num_parameters() + 1; | 466 int arg_count = info_->scope()->num_parameters() + 1; |
467 int arguments_bytes = arg_count * kPointerSize; | 467 int arguments_bytes = arg_count * kPointerSize; |
468 __ Ret(arguments_bytes, rcx); | 468 __ Ret(arguments_bytes, rcx); |
469 | 469 |
470 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 470 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
471 } | 471 } |
472 } | 472 } |
473 | 473 |
474 | 474 |
| 475 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { |
| 476 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 477 } |
| 478 |
| 479 |
| 480 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { |
| 481 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 482 codegen()->GetVar(result_register(), var); |
| 483 } |
| 484 |
| 485 |
475 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 486 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
476 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 487 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
477 MemOperand operand = codegen()->VarOperand(var, result_register()); | 488 MemOperand operand = codegen()->VarOperand(var, result_register()); |
478 __ Push(operand); | 489 __ Push(operand); |
479 } | 490 } |
480 | 491 |
481 | 492 |
| 493 void FullCodeGenerator::TestContext::Plug(Variable* var) const { |
| 494 codegen()->GetVar(result_register(), var); |
| 495 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
| 496 codegen()->DoTest(this); |
| 497 } |
| 498 |
| 499 |
482 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { | 500 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
483 } | 501 } |
484 | 502 |
485 | 503 |
486 void FullCodeGenerator::AccumulatorValueContext::Plug( | 504 void FullCodeGenerator::AccumulatorValueContext::Plug( |
487 Heap::RootListIndex index) const { | 505 Heap::RootListIndex index) const { |
488 __ LoadRoot(result_register(), index); | 506 __ LoadRoot(result_register(), index); |
489 } | 507 } |
490 | 508 |
491 | 509 |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 } | 652 } |
635 | 653 |
636 | 654 |
637 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 655 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
638 Label* materialize_false) const { | 656 Label* materialize_false) const { |
639 DCHECK(materialize_true == true_label_); | 657 DCHECK(materialize_true == true_label_); |
640 DCHECK(materialize_false == false_label_); | 658 DCHECK(materialize_false == false_label_); |
641 } | 659 } |
642 | 660 |
643 | 661 |
| 662 void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
| 663 } |
| 664 |
| 665 |
644 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 666 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
645 Heap::RootListIndex value_root_index = | 667 Heap::RootListIndex value_root_index = |
646 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; | 668 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; |
647 __ LoadRoot(result_register(), value_root_index); | 669 __ LoadRoot(result_register(), value_root_index); |
648 } | 670 } |
649 | 671 |
650 | 672 |
651 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { | 673 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { |
652 Heap::RootListIndex value_root_index = | 674 Heap::RootListIndex value_root_index = |
653 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; | 675 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 __ Push(variable->name()); | 916 __ Push(variable->name()); |
895 __ Push(Smi::FromInt(NONE)); | 917 __ Push(Smi::FromInt(NONE)); |
896 VisitForStackValue(declaration->fun()); | 918 VisitForStackValue(declaration->fun()); |
897 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); | 919 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
898 break; | 920 break; |
899 } | 921 } |
900 } | 922 } |
901 } | 923 } |
902 | 924 |
903 | 925 |
| 926 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) { |
| 927 VariableProxy* proxy = declaration->proxy(); |
| 928 Variable* variable = proxy->var(); |
| 929 switch (variable->location()) { |
| 930 case VariableLocation::UNALLOCATED: |
| 931 case VariableLocation::GLOBAL: |
| 932 // TODO(rossberg) |
| 933 break; |
| 934 |
| 935 case VariableLocation::CONTEXT: { |
| 936 Comment cmnt(masm_, "[ ImportDeclaration"); |
| 937 EmitDebugCheckDeclarationContext(variable); |
| 938 // TODO(rossberg) |
| 939 break; |
| 940 } |
| 941 |
| 942 case VariableLocation::PARAMETER: |
| 943 case VariableLocation::LOCAL: |
| 944 case VariableLocation::LOOKUP: |
| 945 UNREACHABLE(); |
| 946 } |
| 947 } |
| 948 |
| 949 |
| 950 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { |
| 951 // TODO(rossberg) |
| 952 } |
| 953 |
| 954 |
904 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 955 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
905 // Call the runtime to declare the globals. | 956 // Call the runtime to declare the globals. |
906 __ Push(rsi); // The context is the first argument. | 957 __ Push(rsi); // The context is the first argument. |
907 __ Push(pairs); | 958 __ Push(pairs); |
908 __ Push(Smi::FromInt(DeclareGlobalsFlags())); | 959 __ Push(Smi::FromInt(DeclareGlobalsFlags())); |
909 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 960 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
910 // Return value is ignored. | 961 // Return value is ignored. |
911 } | 962 } |
912 | 963 |
913 | 964 |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1223 __ Push(info); | 1274 __ Push(info); |
1224 __ Push(pretenure | 1275 __ Push(pretenure |
1225 ? isolate()->factory()->true_value() | 1276 ? isolate()->factory()->true_value() |
1226 : isolate()->factory()->false_value()); | 1277 : isolate()->factory()->false_value()); |
1227 __ CallRuntime(Runtime::kNewClosure, 3); | 1278 __ CallRuntime(Runtime::kNewClosure, 3); |
1228 } | 1279 } |
1229 context()->Plug(rax); | 1280 context()->Plug(rax); |
1230 } | 1281 } |
1231 | 1282 |
1232 | 1283 |
| 1284 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 1285 Comment cmnt(masm_, "[ VariableProxy"); |
| 1286 EmitVariableLoad(expr); |
| 1287 } |
| 1288 |
| 1289 |
1233 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, | 1290 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, |
1234 int offset, | 1291 int offset, |
1235 FeedbackVectorICSlot slot) { | 1292 FeedbackVectorICSlot slot) { |
1236 if (NeedsHomeObject(initializer)) { | 1293 if (NeedsHomeObject(initializer)) { |
1237 __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0)); | 1294 __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0)); |
1238 __ Move(StoreDescriptor::NameRegister(), | 1295 __ Move(StoreDescriptor::NameRegister(), |
1239 isolate()->factory()->home_object_symbol()); | 1296 isolate()->factory()->home_object_symbol()); |
1240 __ movp(StoreDescriptor::ValueRegister(), | 1297 __ movp(StoreDescriptor::ValueRegister(), |
1241 Operand(rsp, offset * kPointerSize)); | 1298 Operand(rsp, offset * kPointerSize)); |
1242 if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); | 1299 if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); |
(...skipping 2476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3719 __ bind(&null); | 3776 __ bind(&null); |
3720 __ LoadRoot(rax, Heap::kNullValueRootIndex); | 3777 __ LoadRoot(rax, Heap::kNullValueRootIndex); |
3721 | 3778 |
3722 // All done. | 3779 // All done. |
3723 __ bind(&done); | 3780 __ bind(&done); |
3724 | 3781 |
3725 context()->Plug(rax); | 3782 context()->Plug(rax); |
3726 } | 3783 } |
3727 | 3784 |
3728 | 3785 |
| 3786 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { |
| 3787 // Load the arguments on the stack and call the stub. |
| 3788 SubStringStub stub(isolate()); |
| 3789 ZoneList<Expression*>* args = expr->arguments(); |
| 3790 DCHECK(args->length() == 3); |
| 3791 VisitForStackValue(args->at(0)); |
| 3792 VisitForStackValue(args->at(1)); |
| 3793 VisitForStackValue(args->at(2)); |
| 3794 __ CallStub(&stub); |
| 3795 context()->Plug(rax); |
| 3796 } |
| 3797 |
| 3798 |
| 3799 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { |
| 3800 // Load the arguments on the stack and call the stub. |
| 3801 RegExpExecStub stub(isolate()); |
| 3802 ZoneList<Expression*>* args = expr->arguments(); |
| 3803 DCHECK(args->length() == 4); |
| 3804 VisitForStackValue(args->at(0)); |
| 3805 VisitForStackValue(args->at(1)); |
| 3806 VisitForStackValue(args->at(2)); |
| 3807 VisitForStackValue(args->at(3)); |
| 3808 __ CallStub(&stub); |
| 3809 context()->Plug(rax); |
| 3810 } |
| 3811 |
| 3812 |
3729 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { | 3813 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { |
3730 ZoneList<Expression*>* args = expr->arguments(); | 3814 ZoneList<Expression*>* args = expr->arguments(); |
3731 DCHECK(args->length() == 1); | 3815 DCHECK(args->length() == 1); |
3732 | 3816 |
3733 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3817 VisitForAccumulatorValue(args->at(0)); // Load the object. |
3734 | 3818 |
3735 Label done; | 3819 Label done; |
3736 // If the object is a smi return the object. | 3820 // If the object is a smi return the object. |
3737 __ JumpIfSmi(rax, &done); | 3821 __ JumpIfSmi(rax, &done); |
3738 // If the object is not a value type, return the object. | 3822 // If the object is not a value type, return the object. |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3871 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 3955 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
3872 __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); | 3956 __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); |
3873 } | 3957 } |
3874 | 3958 |
3875 __ movw(FieldOperand(string, index, times_2, SeqTwoByteString::kHeaderSize), | 3959 __ movw(FieldOperand(string, index, times_2, SeqTwoByteString::kHeaderSize), |
3876 value); | 3960 value); |
3877 context()->Plug(rax); | 3961 context()->Plug(rax); |
3878 } | 3962 } |
3879 | 3963 |
3880 | 3964 |
| 3965 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { |
| 3966 // Load the arguments on the stack and call the runtime function. |
| 3967 ZoneList<Expression*>* args = expr->arguments(); |
| 3968 DCHECK(args->length() == 2); |
| 3969 VisitForStackValue(args->at(0)); |
| 3970 VisitForStackValue(args->at(1)); |
| 3971 MathPowStub stub(isolate(), MathPowStub::ON_STACK); |
| 3972 __ CallStub(&stub); |
| 3973 context()->Plug(rax); |
| 3974 } |
| 3975 |
| 3976 |
3881 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { | 3977 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { |
3882 ZoneList<Expression*>* args = expr->arguments(); | 3978 ZoneList<Expression*>* args = expr->arguments(); |
3883 DCHECK(args->length() == 2); | 3979 DCHECK(args->length() == 2); |
3884 | 3980 |
3885 VisitForStackValue(args->at(0)); // Load the object. | 3981 VisitForStackValue(args->at(0)); // Load the object. |
3886 VisitForAccumulatorValue(args->at(1)); // Load the value. | 3982 VisitForAccumulatorValue(args->at(1)); // Load the value. |
3887 __ Pop(rbx); // rax = value. rbx = object. | 3983 __ Pop(rbx); // rax = value. rbx = object. |
3888 | 3984 |
3889 Label done; | 3985 Label done; |
3890 // If the object is a smi, return the value. | 3986 // If the object is a smi, return the value. |
3891 __ JumpIfSmi(rbx, &done); | 3987 __ JumpIfSmi(rbx, &done); |
3892 | 3988 |
3893 // If the object is not a value type, return the value. | 3989 // If the object is not a value type, return the value. |
3894 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); | 3990 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); |
3895 __ j(not_equal, &done); | 3991 __ j(not_equal, &done); |
3896 | 3992 |
3897 // Store the value. | 3993 // Store the value. |
3898 __ movp(FieldOperand(rbx, JSValue::kValueOffset), rax); | 3994 __ movp(FieldOperand(rbx, JSValue::kValueOffset), rax); |
3899 // Update the write barrier. Save the value as it will be | 3995 // Update the write barrier. Save the value as it will be |
3900 // overwritten by the write barrier code and is needed afterward. | 3996 // overwritten by the write barrier code and is needed afterward. |
3901 __ movp(rdx, rax); | 3997 __ movp(rdx, rax); |
3902 __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs); | 3998 __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs); |
3903 | 3999 |
3904 __ bind(&done); | 4000 __ bind(&done); |
3905 context()->Plug(rax); | 4001 context()->Plug(rax); |
3906 } | 4002 } |
3907 | 4003 |
| 4004 |
| 4005 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { |
| 4006 ZoneList<Expression*>* args = expr->arguments(); |
| 4007 DCHECK_EQ(args->length(), 1); |
| 4008 |
| 4009 // Load the argument into rax and call the stub. |
| 4010 VisitForAccumulatorValue(args->at(0)); |
| 4011 |
| 4012 NumberToStringStub stub(isolate()); |
| 4013 __ CallStub(&stub); |
| 4014 context()->Plug(rax); |
| 4015 } |
| 4016 |
3908 | 4017 |
3909 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 4018 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
3910 ZoneList<Expression*>* args = expr->arguments(); | 4019 ZoneList<Expression*>* args = expr->arguments(); |
3911 DCHECK(args->length() == 1); | 4020 DCHECK(args->length() == 1); |
3912 | 4021 |
3913 VisitForAccumulatorValue(args->at(0)); | 4022 VisitForAccumulatorValue(args->at(0)); |
3914 | 4023 |
3915 Label done; | 4024 Label done; |
3916 StringCharFromCodeGenerator generator(rax, rbx); | 4025 StringCharFromCodeGenerator generator(rax, rbx); |
3917 generator.GenerateFast(masm_); | 4026 generator.GenerateFast(masm_); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4023 ZoneList<Expression*>* args = expr->arguments(); | 4132 ZoneList<Expression*>* args = expr->arguments(); |
4024 DCHECK_EQ(2, args->length()); | 4133 DCHECK_EQ(2, args->length()); |
4025 VisitForStackValue(args->at(0)); | 4134 VisitForStackValue(args->at(0)); |
4026 VisitForAccumulatorValue(args->at(1)); | 4135 VisitForAccumulatorValue(args->at(1)); |
4027 | 4136 |
4028 __ Pop(rdx); | 4137 __ Pop(rdx); |
4029 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); | 4138 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); |
4030 __ CallStub(&stub); | 4139 __ CallStub(&stub); |
4031 context()->Plug(rax); | 4140 context()->Plug(rax); |
4032 } | 4141 } |
| 4142 |
| 4143 |
| 4144 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { |
| 4145 ZoneList<Expression*>* args = expr->arguments(); |
| 4146 DCHECK_EQ(2, args->length()); |
| 4147 |
| 4148 VisitForStackValue(args->at(0)); |
| 4149 VisitForStackValue(args->at(1)); |
| 4150 |
| 4151 StringCompareStub stub(isolate()); |
| 4152 __ CallStub(&stub); |
| 4153 context()->Plug(rax); |
| 4154 } |
4033 | 4155 |
4034 | 4156 |
4035 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { | 4157 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { |
4036 ZoneList<Expression*>* args = expr->arguments(); | 4158 ZoneList<Expression*>* args = expr->arguments(); |
4037 DCHECK(args->length() >= 2); | 4159 DCHECK(args->length() >= 2); |
4038 | 4160 |
4039 int arg_count = args->length() - 2; // 2 ~ receiver and function. | 4161 int arg_count = args->length() - 2; // 2 ~ receiver and function. |
4040 for (int i = 0; i < arg_count + 1; i++) { | 4162 for (int i = 0; i < arg_count + 1; i++) { |
4041 VisitForStackValue(args->at(i)); | 4163 VisitForStackValue(args->at(i)); |
4042 } | 4164 } |
(...skipping 1300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5343 Assembler::target_address_at(call_target_address, | 5465 Assembler::target_address_at(call_target_address, |
5344 unoptimized_code)); | 5466 unoptimized_code)); |
5345 return OSR_AFTER_STACK_CHECK; | 5467 return OSR_AFTER_STACK_CHECK; |
5346 } | 5468 } |
5347 | 5469 |
5348 | 5470 |
5349 } // namespace internal | 5471 } // namespace internal |
5350 } // namespace v8 | 5472 } // namespace v8 |
5351 | 5473 |
5352 #endif // V8_TARGET_ARCH_X64 | 5474 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |