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_X87 | 7 #if V8_TARGET_ARCH_X87 |
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 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 __ leave(); | 458 __ leave(); |
459 | 459 |
460 int arg_count = info_->scope()->num_parameters() + 1; | 460 int arg_count = info_->scope()->num_parameters() + 1; |
461 int arguments_bytes = arg_count * kPointerSize; | 461 int arguments_bytes = arg_count * kPointerSize; |
462 __ Ret(arguments_bytes, ecx); | 462 __ Ret(arguments_bytes, ecx); |
463 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 463 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
464 } | 464 } |
465 } | 465 } |
466 | 466 |
467 | 467 |
| 468 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { |
| 469 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 470 } |
| 471 |
| 472 |
| 473 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { |
| 474 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 475 codegen()->GetVar(result_register(), var); |
| 476 } |
| 477 |
| 478 |
468 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 479 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
469 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 480 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
470 MemOperand operand = codegen()->VarOperand(var, result_register()); | 481 MemOperand operand = codegen()->VarOperand(var, result_register()); |
471 // Memory operands can be pushed directly. | 482 // Memory operands can be pushed directly. |
472 __ push(operand); | 483 __ push(operand); |
473 } | 484 } |
474 | 485 |
475 | 486 |
| 487 void FullCodeGenerator::TestContext::Plug(Variable* var) const { |
| 488 // For simplicity we always test the accumulator register. |
| 489 codegen()->GetVar(result_register(), var); |
| 490 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
| 491 codegen()->DoTest(this); |
| 492 } |
| 493 |
| 494 |
476 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { | 495 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
477 UNREACHABLE(); // Not used on X87. | 496 UNREACHABLE(); // Not used on X87. |
478 } | 497 } |
479 | 498 |
480 | 499 |
481 void FullCodeGenerator::AccumulatorValueContext::Plug( | 500 void FullCodeGenerator::AccumulatorValueContext::Plug( |
482 Heap::RootListIndex index) const { | 501 Heap::RootListIndex index) const { |
483 UNREACHABLE(); // Not used on X87. | 502 UNREACHABLE(); // Not used on X87. |
484 } | 503 } |
485 | 504 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 } | 635 } |
617 | 636 |
618 | 637 |
619 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 638 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
620 Label* materialize_false) const { | 639 Label* materialize_false) const { |
621 DCHECK(materialize_true == true_label_); | 640 DCHECK(materialize_true == true_label_); |
622 DCHECK(materialize_false == false_label_); | 641 DCHECK(materialize_false == false_label_); |
623 } | 642 } |
624 | 643 |
625 | 644 |
| 645 void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
| 646 } |
| 647 |
| 648 |
626 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 649 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
627 Handle<Object> value = flag | 650 Handle<Object> value = flag |
628 ? isolate()->factory()->true_value() | 651 ? isolate()->factory()->true_value() |
629 : isolate()->factory()->false_value(); | 652 : isolate()->factory()->false_value(); |
630 __ mov(result_register(), value); | 653 __ mov(result_register(), value); |
631 } | 654 } |
632 | 655 |
633 | 656 |
634 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { | 657 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { |
635 Handle<Object> value = flag | 658 Handle<Object> value = flag |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
872 __ push(Immediate(variable->name())); | 895 __ push(Immediate(variable->name())); |
873 __ push(Immediate(Smi::FromInt(NONE))); | 896 __ push(Immediate(Smi::FromInt(NONE))); |
874 VisitForStackValue(declaration->fun()); | 897 VisitForStackValue(declaration->fun()); |
875 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); | 898 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
876 break; | 899 break; |
877 } | 900 } |
878 } | 901 } |
879 } | 902 } |
880 | 903 |
881 | 904 |
| 905 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) { |
| 906 VariableProxy* proxy = declaration->proxy(); |
| 907 Variable* variable = proxy->var(); |
| 908 switch (variable->location()) { |
| 909 case VariableLocation::GLOBAL: |
| 910 case VariableLocation::UNALLOCATED: |
| 911 // TODO(rossberg) |
| 912 break; |
| 913 |
| 914 case VariableLocation::CONTEXT: { |
| 915 Comment cmnt(masm_, "[ ImportDeclaration"); |
| 916 EmitDebugCheckDeclarationContext(variable); |
| 917 // TODO(rossberg) |
| 918 break; |
| 919 } |
| 920 |
| 921 case VariableLocation::PARAMETER: |
| 922 case VariableLocation::LOCAL: |
| 923 case VariableLocation::LOOKUP: |
| 924 UNREACHABLE(); |
| 925 } |
| 926 } |
| 927 |
| 928 |
| 929 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { |
| 930 // TODO(rossberg) |
| 931 } |
| 932 |
| 933 |
882 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 934 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
883 // Call the runtime to declare the globals. | 935 // Call the runtime to declare the globals. |
884 __ push(esi); // The context is the first argument. | 936 __ push(esi); // The context is the first argument. |
885 __ Push(pairs); | 937 __ Push(pairs); |
886 __ Push(Smi::FromInt(DeclareGlobalsFlags())); | 938 __ Push(Smi::FromInt(DeclareGlobalsFlags())); |
887 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 939 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
888 // Return value is ignored. | 940 // Return value is ignored. |
889 } | 941 } |
890 | 942 |
891 | 943 |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1188 __ push(Immediate(info)); | 1240 __ push(Immediate(info)); |
1189 __ push(Immediate(pretenure | 1241 __ push(Immediate(pretenure |
1190 ? isolate()->factory()->true_value() | 1242 ? isolate()->factory()->true_value() |
1191 : isolate()->factory()->false_value())); | 1243 : isolate()->factory()->false_value())); |
1192 __ CallRuntime(Runtime::kNewClosure, 3); | 1244 __ CallRuntime(Runtime::kNewClosure, 3); |
1193 } | 1245 } |
1194 context()->Plug(eax); | 1246 context()->Plug(eax); |
1195 } | 1247 } |
1196 | 1248 |
1197 | 1249 |
| 1250 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 1251 Comment cmnt(masm_, "[ VariableProxy"); |
| 1252 EmitVariableLoad(expr); |
| 1253 } |
| 1254 |
| 1255 |
1198 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, | 1256 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, |
1199 int offset, | 1257 int offset, |
1200 FeedbackVectorICSlot slot) { | 1258 FeedbackVectorICSlot slot) { |
1201 if (NeedsHomeObject(initializer)) { | 1259 if (NeedsHomeObject(initializer)) { |
1202 __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); | 1260 __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); |
1203 __ mov(StoreDescriptor::NameRegister(), | 1261 __ mov(StoreDescriptor::NameRegister(), |
1204 Immediate(isolate()->factory()->home_object_symbol())); | 1262 Immediate(isolate()->factory()->home_object_symbol())); |
1205 __ mov(StoreDescriptor::ValueRegister(), | 1263 __ mov(StoreDescriptor::ValueRegister(), |
1206 Operand(esp, offset * kPointerSize)); | 1264 Operand(esp, offset * kPointerSize)); |
1207 if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); | 1265 if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); |
(...skipping 2515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3723 __ bind(&null); | 3781 __ bind(&null); |
3724 __ mov(eax, isolate()->factory()->null_value()); | 3782 __ mov(eax, isolate()->factory()->null_value()); |
3725 | 3783 |
3726 // All done. | 3784 // All done. |
3727 __ bind(&done); | 3785 __ bind(&done); |
3728 | 3786 |
3729 context()->Plug(eax); | 3787 context()->Plug(eax); |
3730 } | 3788 } |
3731 | 3789 |
3732 | 3790 |
| 3791 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { |
| 3792 // Load the arguments on the stack and call the stub. |
| 3793 SubStringStub stub(isolate()); |
| 3794 ZoneList<Expression*>* args = expr->arguments(); |
| 3795 DCHECK(args->length() == 3); |
| 3796 VisitForStackValue(args->at(0)); |
| 3797 VisitForStackValue(args->at(1)); |
| 3798 VisitForStackValue(args->at(2)); |
| 3799 __ CallStub(&stub); |
| 3800 context()->Plug(eax); |
| 3801 } |
| 3802 |
| 3803 |
| 3804 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { |
| 3805 // Load the arguments on the stack and call the stub. |
| 3806 RegExpExecStub stub(isolate()); |
| 3807 ZoneList<Expression*>* args = expr->arguments(); |
| 3808 DCHECK(args->length() == 4); |
| 3809 VisitForStackValue(args->at(0)); |
| 3810 VisitForStackValue(args->at(1)); |
| 3811 VisitForStackValue(args->at(2)); |
| 3812 VisitForStackValue(args->at(3)); |
| 3813 __ CallStub(&stub); |
| 3814 context()->Plug(eax); |
| 3815 } |
| 3816 |
| 3817 |
3733 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { | 3818 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { |
3734 ZoneList<Expression*>* args = expr->arguments(); | 3819 ZoneList<Expression*>* args = expr->arguments(); |
3735 DCHECK(args->length() == 1); | 3820 DCHECK(args->length() == 1); |
3736 | 3821 |
3737 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3822 VisitForAccumulatorValue(args->at(0)); // Load the object. |
3738 | 3823 |
3739 Label done; | 3824 Label done; |
3740 // If the object is a smi return the object. | 3825 // If the object is a smi return the object. |
3741 __ JumpIfSmi(eax, &done, Label::kNear); | 3826 __ JumpIfSmi(eax, &done, Label::kNear); |
3742 // If the object is not a value type, return the object. | 3827 // If the object is not a value type, return the object. |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3870 } | 3955 } |
3871 | 3956 |
3872 __ SmiUntag(value); | 3957 __ SmiUntag(value); |
3873 // No need to untag a smi for two-byte addressing. | 3958 // No need to untag a smi for two-byte addressing. |
3874 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize), | 3959 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize), |
3875 value); | 3960 value); |
3876 context()->Plug(string); | 3961 context()->Plug(string); |
3877 } | 3962 } |
3878 | 3963 |
3879 | 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 |
| 3972 __ CallRuntime(Runtime::kMathPowSlow, 2); |
| 3973 context()->Plug(eax); |
| 3974 } |
| 3975 |
| 3976 |
3880 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { | 3977 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { |
3881 ZoneList<Expression*>* args = expr->arguments(); | 3978 ZoneList<Expression*>* args = expr->arguments(); |
3882 DCHECK(args->length() == 2); | 3979 DCHECK(args->length() == 2); |
3883 | 3980 |
3884 VisitForStackValue(args->at(0)); // Load the object. | 3981 VisitForStackValue(args->at(0)); // Load the object. |
3885 VisitForAccumulatorValue(args->at(1)); // Load the value. | 3982 VisitForAccumulatorValue(args->at(1)); // Load the value. |
3886 __ pop(ebx); // eax = value. ebx = object. | 3983 __ pop(ebx); // eax = value. ebx = object. |
3887 | 3984 |
3888 Label done; | 3985 Label done; |
3889 // If the object is a smi, return the value. | 3986 // If the object is a smi, return the value. |
3890 __ JumpIfSmi(ebx, &done, Label::kNear); | 3987 __ JumpIfSmi(ebx, &done, Label::kNear); |
3891 | 3988 |
3892 // If the object is not a value type, return the value. | 3989 // If the object is not a value type, return the value. |
3893 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); | 3990 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); |
3894 __ j(not_equal, &done, Label::kNear); | 3991 __ j(not_equal, &done, Label::kNear); |
3895 | 3992 |
3896 // Store the value. | 3993 // Store the value. |
3897 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); | 3994 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); |
3898 | 3995 |
3899 // Update the write barrier. Save the value as it will be | 3996 // Update the write barrier. Save the value as it will be |
3900 // overwritten by the write barrier code and is needed afterward. | 3997 // overwritten by the write barrier code and is needed afterward. |
3901 __ mov(edx, eax); | 3998 __ mov(edx, eax); |
3902 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs); | 3999 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs); |
3903 | 4000 |
3904 __ bind(&done); | 4001 __ bind(&done); |
3905 context()->Plug(eax); | 4002 context()->Plug(eax); |
3906 } | 4003 } |
3907 | 4004 |
| 4005 |
| 4006 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { |
| 4007 ZoneList<Expression*>* args = expr->arguments(); |
| 4008 DCHECK_EQ(args->length(), 1); |
| 4009 |
| 4010 // Load the argument into eax and call the stub. |
| 4011 VisitForAccumulatorValue(args->at(0)); |
| 4012 |
| 4013 NumberToStringStub stub(isolate()); |
| 4014 __ CallStub(&stub); |
| 4015 context()->Plug(eax); |
| 4016 } |
| 4017 |
3908 | 4018 |
3909 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 4019 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
3910 ZoneList<Expression*>* args = expr->arguments(); | 4020 ZoneList<Expression*>* args = expr->arguments(); |
3911 DCHECK(args->length() == 1); | 4021 DCHECK(args->length() == 1); |
3912 | 4022 |
3913 VisitForAccumulatorValue(args->at(0)); | 4023 VisitForAccumulatorValue(args->at(0)); |
3914 | 4024 |
3915 Label done; | 4025 Label done; |
3916 StringCharFromCodeGenerator generator(eax, ebx); | 4026 StringCharFromCodeGenerator generator(eax, ebx); |
3917 generator.GenerateFast(masm_); | 4027 generator.GenerateFast(masm_); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4023 ZoneList<Expression*>* args = expr->arguments(); | 4133 ZoneList<Expression*>* args = expr->arguments(); |
4024 DCHECK_EQ(2, args->length()); | 4134 DCHECK_EQ(2, args->length()); |
4025 VisitForStackValue(args->at(0)); | 4135 VisitForStackValue(args->at(0)); |
4026 VisitForAccumulatorValue(args->at(1)); | 4136 VisitForAccumulatorValue(args->at(1)); |
4027 | 4137 |
4028 __ pop(edx); | 4138 __ pop(edx); |
4029 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); | 4139 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); |
4030 __ CallStub(&stub); | 4140 __ CallStub(&stub); |
4031 context()->Plug(eax); | 4141 context()->Plug(eax); |
4032 } | 4142 } |
| 4143 |
| 4144 |
| 4145 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { |
| 4146 ZoneList<Expression*>* args = expr->arguments(); |
| 4147 DCHECK_EQ(2, args->length()); |
| 4148 |
| 4149 VisitForStackValue(args->at(0)); |
| 4150 VisitForStackValue(args->at(1)); |
| 4151 |
| 4152 StringCompareStub stub(isolate()); |
| 4153 __ CallStub(&stub); |
| 4154 context()->Plug(eax); |
| 4155 } |
4033 | 4156 |
4034 | 4157 |
4035 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { | 4158 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { |
4036 ZoneList<Expression*>* args = expr->arguments(); | 4159 ZoneList<Expression*>* args = expr->arguments(); |
4037 DCHECK(args->length() >= 2); | 4160 DCHECK(args->length() >= 2); |
4038 | 4161 |
4039 int arg_count = args->length() - 2; // 2 ~ receiver and function. | 4162 int arg_count = args->length() - 2; // 2 ~ receiver and function. |
4040 for (int i = 0; i < arg_count + 1; ++i) { | 4163 for (int i = 0; i < arg_count + 1; ++i) { |
4041 VisitForStackValue(args->at(i)); | 4164 VisitForStackValue(args->at(i)); |
4042 } | 4165 } |
(...skipping 1272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5315 Assembler::target_address_at(call_target_address, | 5438 Assembler::target_address_at(call_target_address, |
5316 unoptimized_code)); | 5439 unoptimized_code)); |
5317 return OSR_AFTER_STACK_CHECK; | 5440 return OSR_AFTER_STACK_CHECK; |
5318 } | 5441 } |
5319 | 5442 |
5320 | 5443 |
5321 } // namespace internal | 5444 } // namespace internal |
5322 } // namespace v8 | 5445 } // namespace v8 |
5323 | 5446 |
5324 #endif // V8_TARGET_ARCH_X87 | 5447 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |