| 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_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
| 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 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 __ leave(); | 461 __ leave(); |
| 462 | 462 |
| 463 int arg_count = info_->scope()->num_parameters() + 1; | 463 int arg_count = info_->scope()->num_parameters() + 1; |
| 464 int arguments_bytes = arg_count * kPointerSize; | 464 int arguments_bytes = arg_count * kPointerSize; |
| 465 __ Ret(arguments_bytes, ecx); | 465 __ Ret(arguments_bytes, ecx); |
| 466 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 466 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
| 467 } | 467 } |
| 468 } | 468 } |
| 469 | 469 |
| 470 | 470 |
| 471 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { |
| 472 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 473 } |
| 474 |
| 475 |
| 476 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { |
| 477 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 478 codegen()->GetVar(result_register(), var); |
| 479 } |
| 480 |
| 481 |
| 471 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 482 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
| 472 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 483 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 473 MemOperand operand = codegen()->VarOperand(var, result_register()); | 484 MemOperand operand = codegen()->VarOperand(var, result_register()); |
| 474 // Memory operands can be pushed directly. | 485 // Memory operands can be pushed directly. |
| 475 __ push(operand); | 486 __ push(operand); |
| 476 } | 487 } |
| 477 | 488 |
| 478 | 489 |
| 490 void FullCodeGenerator::TestContext::Plug(Variable* var) const { |
| 491 // For simplicity we always test the accumulator register. |
| 492 codegen()->GetVar(result_register(), var); |
| 493 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
| 494 codegen()->DoTest(this); |
| 495 } |
| 496 |
| 497 |
| 479 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { | 498 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
| 480 UNREACHABLE(); // Not used on IA32. | 499 UNREACHABLE(); // Not used on IA32. |
| 481 } | 500 } |
| 482 | 501 |
| 483 | 502 |
| 484 void FullCodeGenerator::AccumulatorValueContext::Plug( | 503 void FullCodeGenerator::AccumulatorValueContext::Plug( |
| 485 Heap::RootListIndex index) const { | 504 Heap::RootListIndex index) const { |
| 486 UNREACHABLE(); // Not used on IA32. | 505 UNREACHABLE(); // Not used on IA32. |
| 487 } | 506 } |
| 488 | 507 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 } | 638 } |
| 620 | 639 |
| 621 | 640 |
| 622 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 641 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
| 623 Label* materialize_false) const { | 642 Label* materialize_false) const { |
| 624 DCHECK(materialize_true == true_label_); | 643 DCHECK(materialize_true == true_label_); |
| 625 DCHECK(materialize_false == false_label_); | 644 DCHECK(materialize_false == false_label_); |
| 626 } | 645 } |
| 627 | 646 |
| 628 | 647 |
| 648 void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
| 649 } |
| 650 |
| 651 |
| 629 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 652 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
| 630 Handle<Object> value = flag | 653 Handle<Object> value = flag |
| 631 ? isolate()->factory()->true_value() | 654 ? isolate()->factory()->true_value() |
| 632 : isolate()->factory()->false_value(); | 655 : isolate()->factory()->false_value(); |
| 633 __ mov(result_register(), value); | 656 __ mov(result_register(), value); |
| 634 } | 657 } |
| 635 | 658 |
| 636 | 659 |
| 637 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { | 660 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { |
| 638 Handle<Object> value = flag | 661 Handle<Object> value = flag |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 __ push(Immediate(variable->name())); | 902 __ push(Immediate(variable->name())); |
| 880 __ push(Immediate(Smi::FromInt(NONE))); | 903 __ push(Immediate(Smi::FromInt(NONE))); |
| 881 VisitForStackValue(declaration->fun()); | 904 VisitForStackValue(declaration->fun()); |
| 882 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); | 905 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
| 883 break; | 906 break; |
| 884 } | 907 } |
| 885 } | 908 } |
| 886 } | 909 } |
| 887 | 910 |
| 888 | 911 |
| 912 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) { |
| 913 VariableProxy* proxy = declaration->proxy(); |
| 914 Variable* variable = proxy->var(); |
| 915 switch (variable->location()) { |
| 916 case VariableLocation::GLOBAL: |
| 917 case VariableLocation::UNALLOCATED: |
| 918 // TODO(rossberg) |
| 919 break; |
| 920 |
| 921 case VariableLocation::CONTEXT: { |
| 922 Comment cmnt(masm_, "[ ImportDeclaration"); |
| 923 EmitDebugCheckDeclarationContext(variable); |
| 924 // TODO(rossberg) |
| 925 break; |
| 926 } |
| 927 |
| 928 case VariableLocation::PARAMETER: |
| 929 case VariableLocation::LOCAL: |
| 930 case VariableLocation::LOOKUP: |
| 931 UNREACHABLE(); |
| 932 } |
| 933 } |
| 934 |
| 935 |
| 936 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { |
| 937 // TODO(rossberg) |
| 938 } |
| 939 |
| 940 |
| 889 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 941 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 890 // Call the runtime to declare the globals. | 942 // Call the runtime to declare the globals. |
| 891 __ push(esi); // The context is the first argument. | 943 __ push(esi); // The context is the first argument. |
| 892 __ Push(pairs); | 944 __ Push(pairs); |
| 893 __ Push(Smi::FromInt(DeclareGlobalsFlags())); | 945 __ Push(Smi::FromInt(DeclareGlobalsFlags())); |
| 894 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 946 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
| 895 // Return value is ignored. | 947 // Return value is ignored. |
| 896 } | 948 } |
| 897 | 949 |
| 898 | 950 |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1195 __ push(Immediate(info)); | 1247 __ push(Immediate(info)); |
| 1196 __ push(Immediate(pretenure | 1248 __ push(Immediate(pretenure |
| 1197 ? isolate()->factory()->true_value() | 1249 ? isolate()->factory()->true_value() |
| 1198 : isolate()->factory()->false_value())); | 1250 : isolate()->factory()->false_value())); |
| 1199 __ CallRuntime(Runtime::kNewClosure, 3); | 1251 __ CallRuntime(Runtime::kNewClosure, 3); |
| 1200 } | 1252 } |
| 1201 context()->Plug(eax); | 1253 context()->Plug(eax); |
| 1202 } | 1254 } |
| 1203 | 1255 |
| 1204 | 1256 |
| 1257 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 1258 Comment cmnt(masm_, "[ VariableProxy"); |
| 1259 EmitVariableLoad(expr); |
| 1260 } |
| 1261 |
| 1262 |
| 1205 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, | 1263 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, |
| 1206 int offset, | 1264 int offset, |
| 1207 FeedbackVectorICSlot slot) { | 1265 FeedbackVectorICSlot slot) { |
| 1208 if (NeedsHomeObject(initializer)) { | 1266 if (NeedsHomeObject(initializer)) { |
| 1209 __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); | 1267 __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); |
| 1210 __ mov(StoreDescriptor::NameRegister(), | 1268 __ mov(StoreDescriptor::NameRegister(), |
| 1211 Immediate(isolate()->factory()->home_object_symbol())); | 1269 Immediate(isolate()->factory()->home_object_symbol())); |
| 1212 __ mov(StoreDescriptor::ValueRegister(), | 1270 __ mov(StoreDescriptor::ValueRegister(), |
| 1213 Operand(esp, offset * kPointerSize)); | 1271 Operand(esp, offset * kPointerSize)); |
| 1214 if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); | 1272 if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); |
| (...skipping 2517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3732 __ bind(&null); | 3790 __ bind(&null); |
| 3733 __ mov(eax, isolate()->factory()->null_value()); | 3791 __ mov(eax, isolate()->factory()->null_value()); |
| 3734 | 3792 |
| 3735 // All done. | 3793 // All done. |
| 3736 __ bind(&done); | 3794 __ bind(&done); |
| 3737 | 3795 |
| 3738 context()->Plug(eax); | 3796 context()->Plug(eax); |
| 3739 } | 3797 } |
| 3740 | 3798 |
| 3741 | 3799 |
| 3800 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { |
| 3801 // Load the arguments on the stack and call the stub. |
| 3802 SubStringStub stub(isolate()); |
| 3803 ZoneList<Expression*>* args = expr->arguments(); |
| 3804 DCHECK(args->length() == 3); |
| 3805 VisitForStackValue(args->at(0)); |
| 3806 VisitForStackValue(args->at(1)); |
| 3807 VisitForStackValue(args->at(2)); |
| 3808 __ CallStub(&stub); |
| 3809 context()->Plug(eax); |
| 3810 } |
| 3811 |
| 3812 |
| 3813 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { |
| 3814 // Load the arguments on the stack and call the stub. |
| 3815 RegExpExecStub stub(isolate()); |
| 3816 ZoneList<Expression*>* args = expr->arguments(); |
| 3817 DCHECK(args->length() == 4); |
| 3818 VisitForStackValue(args->at(0)); |
| 3819 VisitForStackValue(args->at(1)); |
| 3820 VisitForStackValue(args->at(2)); |
| 3821 VisitForStackValue(args->at(3)); |
| 3822 __ CallStub(&stub); |
| 3823 context()->Plug(eax); |
| 3824 } |
| 3825 |
| 3826 |
| 3742 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { | 3827 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { |
| 3743 ZoneList<Expression*>* args = expr->arguments(); | 3828 ZoneList<Expression*>* args = expr->arguments(); |
| 3744 DCHECK(args->length() == 1); | 3829 DCHECK(args->length() == 1); |
| 3745 | 3830 |
| 3746 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3831 VisitForAccumulatorValue(args->at(0)); // Load the object. |
| 3747 | 3832 |
| 3748 Label done; | 3833 Label done; |
| 3749 // If the object is a smi return the object. | 3834 // If the object is a smi return the object. |
| 3750 __ JumpIfSmi(eax, &done, Label::kNear); | 3835 __ JumpIfSmi(eax, &done, Label::kNear); |
| 3751 // If the object is not a value type, return the object. | 3836 // If the object is not a value type, return the object. |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3879 } | 3964 } |
| 3880 | 3965 |
| 3881 __ SmiUntag(value); | 3966 __ SmiUntag(value); |
| 3882 // No need to untag a smi for two-byte addressing. | 3967 // No need to untag a smi for two-byte addressing. |
| 3883 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize), | 3968 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize), |
| 3884 value); | 3969 value); |
| 3885 context()->Plug(string); | 3970 context()->Plug(string); |
| 3886 } | 3971 } |
| 3887 | 3972 |
| 3888 | 3973 |
| 3974 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { |
| 3975 // Load the arguments on the stack and call the runtime function. |
| 3976 ZoneList<Expression*>* args = expr->arguments(); |
| 3977 DCHECK(args->length() == 2); |
| 3978 VisitForStackValue(args->at(0)); |
| 3979 VisitForStackValue(args->at(1)); |
| 3980 |
| 3981 MathPowStub stub(isolate(), MathPowStub::ON_STACK); |
| 3982 __ CallStub(&stub); |
| 3983 context()->Plug(eax); |
| 3984 } |
| 3985 |
| 3986 |
| 3889 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { | 3987 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { |
| 3890 ZoneList<Expression*>* args = expr->arguments(); | 3988 ZoneList<Expression*>* args = expr->arguments(); |
| 3891 DCHECK(args->length() == 2); | 3989 DCHECK(args->length() == 2); |
| 3892 | 3990 |
| 3893 VisitForStackValue(args->at(0)); // Load the object. | 3991 VisitForStackValue(args->at(0)); // Load the object. |
| 3894 VisitForAccumulatorValue(args->at(1)); // Load the value. | 3992 VisitForAccumulatorValue(args->at(1)); // Load the value. |
| 3895 __ pop(ebx); // eax = value. ebx = object. | 3993 __ pop(ebx); // eax = value. ebx = object. |
| 3896 | 3994 |
| 3897 Label done; | 3995 Label done; |
| 3898 // If the object is a smi, return the value. | 3996 // If the object is a smi, return the value. |
| 3899 __ JumpIfSmi(ebx, &done, Label::kNear); | 3997 __ JumpIfSmi(ebx, &done, Label::kNear); |
| 3900 | 3998 |
| 3901 // If the object is not a value type, return the value. | 3999 // If the object is not a value type, return the value. |
| 3902 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); | 4000 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); |
| 3903 __ j(not_equal, &done, Label::kNear); | 4001 __ j(not_equal, &done, Label::kNear); |
| 3904 | 4002 |
| 3905 // Store the value. | 4003 // Store the value. |
| 3906 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); | 4004 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); |
| 3907 | 4005 |
| 3908 // Update the write barrier. Save the value as it will be | 4006 // Update the write barrier. Save the value as it will be |
| 3909 // overwritten by the write barrier code and is needed afterward. | 4007 // overwritten by the write barrier code and is needed afterward. |
| 3910 __ mov(edx, eax); | 4008 __ mov(edx, eax); |
| 3911 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs); | 4009 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs); |
| 3912 | 4010 |
| 3913 __ bind(&done); | 4011 __ bind(&done); |
| 3914 context()->Plug(eax); | 4012 context()->Plug(eax); |
| 3915 } | 4013 } |
| 3916 | 4014 |
| 4015 |
| 4016 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { |
| 4017 ZoneList<Expression*>* args = expr->arguments(); |
| 4018 DCHECK_EQ(args->length(), 1); |
| 4019 |
| 4020 // Load the argument into eax and call the stub. |
| 4021 VisitForAccumulatorValue(args->at(0)); |
| 4022 |
| 4023 NumberToStringStub stub(isolate()); |
| 4024 __ CallStub(&stub); |
| 4025 context()->Plug(eax); |
| 4026 } |
| 4027 |
| 3917 | 4028 |
| 3918 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 4029 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
| 3919 ZoneList<Expression*>* args = expr->arguments(); | 4030 ZoneList<Expression*>* args = expr->arguments(); |
| 3920 DCHECK(args->length() == 1); | 4031 DCHECK(args->length() == 1); |
| 3921 | 4032 |
| 3922 VisitForAccumulatorValue(args->at(0)); | 4033 VisitForAccumulatorValue(args->at(0)); |
| 3923 | 4034 |
| 3924 Label done; | 4035 Label done; |
| 3925 StringCharFromCodeGenerator generator(eax, ebx); | 4036 StringCharFromCodeGenerator generator(eax, ebx); |
| 3926 generator.GenerateFast(masm_); | 4037 generator.GenerateFast(masm_); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4032 ZoneList<Expression*>* args = expr->arguments(); | 4143 ZoneList<Expression*>* args = expr->arguments(); |
| 4033 DCHECK_EQ(2, args->length()); | 4144 DCHECK_EQ(2, args->length()); |
| 4034 VisitForStackValue(args->at(0)); | 4145 VisitForStackValue(args->at(0)); |
| 4035 VisitForAccumulatorValue(args->at(1)); | 4146 VisitForAccumulatorValue(args->at(1)); |
| 4036 | 4147 |
| 4037 __ pop(edx); | 4148 __ pop(edx); |
| 4038 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); | 4149 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); |
| 4039 __ CallStub(&stub); | 4150 __ CallStub(&stub); |
| 4040 context()->Plug(eax); | 4151 context()->Plug(eax); |
| 4041 } | 4152 } |
| 4153 |
| 4154 |
| 4155 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { |
| 4156 ZoneList<Expression*>* args = expr->arguments(); |
| 4157 DCHECK_EQ(2, args->length()); |
| 4158 |
| 4159 VisitForStackValue(args->at(0)); |
| 4160 VisitForStackValue(args->at(1)); |
| 4161 |
| 4162 StringCompareStub stub(isolate()); |
| 4163 __ CallStub(&stub); |
| 4164 context()->Plug(eax); |
| 4165 } |
| 4042 | 4166 |
| 4043 | 4167 |
| 4044 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { | 4168 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { |
| 4045 ZoneList<Expression*>* args = expr->arguments(); | 4169 ZoneList<Expression*>* args = expr->arguments(); |
| 4046 DCHECK(args->length() >= 2); | 4170 DCHECK(args->length() >= 2); |
| 4047 | 4171 |
| 4048 int arg_count = args->length() - 2; // 2 ~ receiver and function. | 4172 int arg_count = args->length() - 2; // 2 ~ receiver and function. |
| 4049 for (int i = 0; i < arg_count + 1; ++i) { | 4173 for (int i = 0; i < arg_count + 1; ++i) { |
| 4050 VisitForStackValue(args->at(i)); | 4174 VisitForStackValue(args->at(i)); |
| 4051 } | 4175 } |
| (...skipping 1272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5324 Assembler::target_address_at(call_target_address, | 5448 Assembler::target_address_at(call_target_address, |
| 5325 unoptimized_code)); | 5449 unoptimized_code)); |
| 5326 return OSR_AFTER_STACK_CHECK; | 5450 return OSR_AFTER_STACK_CHECK; |
| 5327 } | 5451 } |
| 5328 | 5452 |
| 5329 | 5453 |
| 5330 } // namespace internal | 5454 } // namespace internal |
| 5331 } // namespace v8 | 5455 } // namespace v8 |
| 5332 | 5456 |
| 5333 #endif // V8_TARGET_ARCH_IA32 | 5457 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |