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_ARM | 7 #if V8_TARGET_ARCH_ARM |
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 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 { ConstantPoolUnavailableScope constant_pool_unavailable(masm_); | 502 { ConstantPoolUnavailableScope constant_pool_unavailable(masm_); |
503 __ add(sp, sp, Operand(sp_delta)); | 503 __ add(sp, sp, Operand(sp_delta)); |
504 __ Jump(lr); | 504 __ Jump(lr); |
505 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 505 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
506 } | 506 } |
507 } | 507 } |
508 } | 508 } |
509 } | 509 } |
510 | 510 |
511 | 511 |
| 512 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { |
| 513 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 514 } |
| 515 |
| 516 |
| 517 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { |
| 518 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 519 codegen()->GetVar(result_register(), var); |
| 520 } |
| 521 |
| 522 |
512 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 523 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
513 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 524 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
514 codegen()->GetVar(result_register(), var); | 525 codegen()->GetVar(result_register(), var); |
515 __ push(result_register()); | 526 __ push(result_register()); |
516 } | 527 } |
517 | 528 |
518 | 529 |
| 530 void FullCodeGenerator::TestContext::Plug(Variable* var) const { |
| 531 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 532 // For simplicity we always test the accumulator register. |
| 533 codegen()->GetVar(result_register(), var); |
| 534 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
| 535 codegen()->DoTest(this); |
| 536 } |
| 537 |
| 538 |
519 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { | 539 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
520 } | 540 } |
521 | 541 |
522 | 542 |
523 void FullCodeGenerator::AccumulatorValueContext::Plug( | 543 void FullCodeGenerator::AccumulatorValueContext::Plug( |
524 Heap::RootListIndex index) const { | 544 Heap::RootListIndex index) const { |
525 __ LoadRoot(result_register(), index); | 545 __ LoadRoot(result_register(), index); |
526 } | 546 } |
527 | 547 |
528 | 548 |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 } | 687 } |
668 | 688 |
669 | 689 |
670 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 690 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
671 Label* materialize_false) const { | 691 Label* materialize_false) const { |
672 DCHECK(materialize_true == true_label_); | 692 DCHECK(materialize_true == true_label_); |
673 DCHECK(materialize_false == false_label_); | 693 DCHECK(materialize_false == false_label_); |
674 } | 694 } |
675 | 695 |
676 | 696 |
| 697 void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
| 698 } |
| 699 |
| 700 |
677 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 701 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
678 Heap::RootListIndex value_root_index = | 702 Heap::RootListIndex value_root_index = |
679 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; | 703 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; |
680 __ LoadRoot(result_register(), value_root_index); | 704 __ LoadRoot(result_register(), value_root_index); |
681 } | 705 } |
682 | 706 |
683 | 707 |
684 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { | 708 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { |
685 Heap::RootListIndex value_root_index = | 709 Heap::RootListIndex value_root_index = |
686 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; | 710 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
935 __ Push(cp, r2, r1); | 959 __ Push(cp, r2, r1); |
936 // Push initial value for function declaration. | 960 // Push initial value for function declaration. |
937 VisitForStackValue(declaration->fun()); | 961 VisitForStackValue(declaration->fun()); |
938 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); | 962 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
939 break; | 963 break; |
940 } | 964 } |
941 } | 965 } |
942 } | 966 } |
943 | 967 |
944 | 968 |
| 969 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) { |
| 970 VariableProxy* proxy = declaration->proxy(); |
| 971 Variable* variable = proxy->var(); |
| 972 switch (variable->location()) { |
| 973 case VariableLocation::GLOBAL: |
| 974 case VariableLocation::UNALLOCATED: |
| 975 // TODO(rossberg) |
| 976 break; |
| 977 |
| 978 case VariableLocation::CONTEXT: { |
| 979 Comment cmnt(masm_, "[ ImportDeclaration"); |
| 980 EmitDebugCheckDeclarationContext(variable); |
| 981 // TODO(rossberg) |
| 982 break; |
| 983 } |
| 984 |
| 985 case VariableLocation::PARAMETER: |
| 986 case VariableLocation::LOCAL: |
| 987 case VariableLocation::LOOKUP: |
| 988 UNREACHABLE(); |
| 989 } |
| 990 } |
| 991 |
| 992 |
| 993 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { |
| 994 // TODO(rossberg) |
| 995 } |
| 996 |
| 997 |
945 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 998 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
946 // Call the runtime to declare the globals. | 999 // Call the runtime to declare the globals. |
947 // The context is the first argument. | 1000 // The context is the first argument. |
948 __ mov(r1, Operand(pairs)); | 1001 __ mov(r1, Operand(pairs)); |
949 __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); | 1002 __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); |
950 __ Push(cp, r1, r0); | 1003 __ Push(cp, r1, r0); |
951 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 1004 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
952 // Return value is ignored. | 1005 // Return value is ignored. |
953 } | 1006 } |
954 | 1007 |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 __ mov(r0, Operand(info)); | 1319 __ mov(r0, Operand(info)); |
1267 __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex | 1320 __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex |
1268 : Heap::kFalseValueRootIndex); | 1321 : Heap::kFalseValueRootIndex); |
1269 __ Push(cp, r0, r1); | 1322 __ Push(cp, r0, r1); |
1270 __ CallRuntime(Runtime::kNewClosure, 3); | 1323 __ CallRuntime(Runtime::kNewClosure, 3); |
1271 } | 1324 } |
1272 context()->Plug(r0); | 1325 context()->Plug(r0); |
1273 } | 1326 } |
1274 | 1327 |
1275 | 1328 |
| 1329 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 1330 Comment cmnt(masm_, "[ VariableProxy"); |
| 1331 EmitVariableLoad(expr); |
| 1332 } |
| 1333 |
| 1334 |
1276 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, | 1335 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, |
1277 int offset, | 1336 int offset, |
1278 FeedbackVectorICSlot slot) { | 1337 FeedbackVectorICSlot slot) { |
1279 if (NeedsHomeObject(initializer)) { | 1338 if (NeedsHomeObject(initializer)) { |
1280 __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); | 1339 __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); |
1281 __ mov(StoreDescriptor::NameRegister(), | 1340 __ mov(StoreDescriptor::NameRegister(), |
1282 Operand(isolate()->factory()->home_object_symbol())); | 1341 Operand(isolate()->factory()->home_object_symbol())); |
1283 __ ldr(StoreDescriptor::ValueRegister(), | 1342 __ ldr(StoreDescriptor::ValueRegister(), |
1284 MemOperand(sp, offset * kPointerSize)); | 1343 MemOperand(sp, offset * kPointerSize)); |
1285 if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); | 1344 if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); |
(...skipping 2554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3840 __ bind(&null); | 3899 __ bind(&null); |
3841 __ LoadRoot(r0, Heap::kNullValueRootIndex); | 3900 __ LoadRoot(r0, Heap::kNullValueRootIndex); |
3842 | 3901 |
3843 // All done. | 3902 // All done. |
3844 __ bind(&done); | 3903 __ bind(&done); |
3845 | 3904 |
3846 context()->Plug(r0); | 3905 context()->Plug(r0); |
3847 } | 3906 } |
3848 | 3907 |
3849 | 3908 |
| 3909 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { |
| 3910 // Load the arguments on the stack and call the stub. |
| 3911 SubStringStub stub(isolate()); |
| 3912 ZoneList<Expression*>* args = expr->arguments(); |
| 3913 DCHECK(args->length() == 3); |
| 3914 VisitForStackValue(args->at(0)); |
| 3915 VisitForStackValue(args->at(1)); |
| 3916 VisitForStackValue(args->at(2)); |
| 3917 __ CallStub(&stub); |
| 3918 context()->Plug(r0); |
| 3919 } |
| 3920 |
| 3921 |
| 3922 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { |
| 3923 // Load the arguments on the stack and call the stub. |
| 3924 RegExpExecStub stub(isolate()); |
| 3925 ZoneList<Expression*>* args = expr->arguments(); |
| 3926 DCHECK(args->length() == 4); |
| 3927 VisitForStackValue(args->at(0)); |
| 3928 VisitForStackValue(args->at(1)); |
| 3929 VisitForStackValue(args->at(2)); |
| 3930 VisitForStackValue(args->at(3)); |
| 3931 __ CallStub(&stub); |
| 3932 context()->Plug(r0); |
| 3933 } |
| 3934 |
| 3935 |
3850 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { | 3936 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { |
3851 ZoneList<Expression*>* args = expr->arguments(); | 3937 ZoneList<Expression*>* args = expr->arguments(); |
3852 DCHECK(args->length() == 1); | 3938 DCHECK(args->length() == 1); |
3853 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3939 VisitForAccumulatorValue(args->at(0)); // Load the object. |
3854 | 3940 |
3855 Label done; | 3941 Label done; |
3856 // If the object is a smi return the object. | 3942 // If the object is a smi return the object. |
3857 __ JumpIfSmi(r0, &done); | 3943 __ JumpIfSmi(r0, &done); |
3858 // If the object is not a value type, return the object. | 3944 // If the object is not a value type, return the object. |
3859 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); | 3945 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3985 __ SmiUntag(value, value); | 4071 __ SmiUntag(value, value); |
3986 __ add(ip, | 4072 __ add(ip, |
3987 string, | 4073 string, |
3988 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 4074 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
3989 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 4075 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
3990 __ strh(value, MemOperand(ip, index)); | 4076 __ strh(value, MemOperand(ip, index)); |
3991 context()->Plug(string); | 4077 context()->Plug(string); |
3992 } | 4078 } |
3993 | 4079 |
3994 | 4080 |
| 4081 |
| 4082 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { |
| 4083 // Load the arguments on the stack and call the runtime function. |
| 4084 ZoneList<Expression*>* args = expr->arguments(); |
| 4085 DCHECK(args->length() == 2); |
| 4086 VisitForStackValue(args->at(0)); |
| 4087 VisitForStackValue(args->at(1)); |
| 4088 MathPowStub stub(isolate(), MathPowStub::ON_STACK); |
| 4089 __ CallStub(&stub); |
| 4090 context()->Plug(r0); |
| 4091 } |
| 4092 |
| 4093 |
3995 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { | 4094 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { |
3996 ZoneList<Expression*>* args = expr->arguments(); | 4095 ZoneList<Expression*>* args = expr->arguments(); |
3997 DCHECK(args->length() == 2); | 4096 DCHECK(args->length() == 2); |
3998 VisitForStackValue(args->at(0)); // Load the object. | 4097 VisitForStackValue(args->at(0)); // Load the object. |
3999 VisitForAccumulatorValue(args->at(1)); // Load the value. | 4098 VisitForAccumulatorValue(args->at(1)); // Load the value. |
4000 __ pop(r1); // r0 = value. r1 = object. | 4099 __ pop(r1); // r0 = value. r1 = object. |
4001 | 4100 |
4002 Label done; | 4101 Label done; |
4003 // If the object is a smi, return the value. | 4102 // If the object is a smi, return the value. |
4004 __ JumpIfSmi(r1, &done); | 4103 __ JumpIfSmi(r1, &done); |
4005 | 4104 |
4006 // If the object is not a value type, return the value. | 4105 // If the object is not a value type, return the value. |
4007 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); | 4106 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); |
4008 __ b(ne, &done); | 4107 __ b(ne, &done); |
4009 | 4108 |
4010 // Store the value. | 4109 // Store the value. |
4011 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); | 4110 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); |
4012 // Update the write barrier. Save the value as it will be | 4111 // Update the write barrier. Save the value as it will be |
4013 // overwritten by the write barrier code and is needed afterward. | 4112 // overwritten by the write barrier code and is needed afterward. |
4014 __ mov(r2, r0); | 4113 __ mov(r2, r0); |
4015 __ RecordWriteField( | 4114 __ RecordWriteField( |
4016 r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); | 4115 r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); |
4017 | 4116 |
4018 __ bind(&done); | 4117 __ bind(&done); |
4019 context()->Plug(r0); | 4118 context()->Plug(r0); |
4020 } | 4119 } |
4021 | 4120 |
| 4121 |
| 4122 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { |
| 4123 ZoneList<Expression*>* args = expr->arguments(); |
| 4124 DCHECK_EQ(args->length(), 1); |
| 4125 // Load the argument into r0 and call the stub. |
| 4126 VisitForAccumulatorValue(args->at(0)); |
| 4127 |
| 4128 NumberToStringStub stub(isolate()); |
| 4129 __ CallStub(&stub); |
| 4130 context()->Plug(r0); |
| 4131 } |
| 4132 |
4022 | 4133 |
4023 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 4134 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
4024 ZoneList<Expression*>* args = expr->arguments(); | 4135 ZoneList<Expression*>* args = expr->arguments(); |
4025 DCHECK(args->length() == 1); | 4136 DCHECK(args->length() == 1); |
4026 VisitForAccumulatorValue(args->at(0)); | 4137 VisitForAccumulatorValue(args->at(0)); |
4027 | 4138 |
4028 Label done; | 4139 Label done; |
4029 StringCharFromCodeGenerator generator(r0, r1); | 4140 StringCharFromCodeGenerator generator(r0, r1); |
4030 generator.GenerateFast(masm_); | 4141 generator.GenerateFast(masm_); |
4031 __ jmp(&done); | 4142 __ jmp(&done); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4134 ZoneList<Expression*>* args = expr->arguments(); | 4245 ZoneList<Expression*>* args = expr->arguments(); |
4135 DCHECK_EQ(2, args->length()); | 4246 DCHECK_EQ(2, args->length()); |
4136 VisitForStackValue(args->at(0)); | 4247 VisitForStackValue(args->at(0)); |
4137 VisitForAccumulatorValue(args->at(1)); | 4248 VisitForAccumulatorValue(args->at(1)); |
4138 | 4249 |
4139 __ pop(r1); | 4250 __ pop(r1); |
4140 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); | 4251 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); |
4141 __ CallStub(&stub); | 4252 __ CallStub(&stub); |
4142 context()->Plug(r0); | 4253 context()->Plug(r0); |
4143 } | 4254 } |
| 4255 |
| 4256 |
| 4257 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { |
| 4258 ZoneList<Expression*>* args = expr->arguments(); |
| 4259 DCHECK_EQ(2, args->length()); |
| 4260 VisitForStackValue(args->at(0)); |
| 4261 VisitForStackValue(args->at(1)); |
| 4262 |
| 4263 StringCompareStub stub(isolate()); |
| 4264 __ CallStub(&stub); |
| 4265 context()->Plug(r0); |
| 4266 } |
4144 | 4267 |
4145 | 4268 |
4146 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { | 4269 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { |
4147 ZoneList<Expression*>* args = expr->arguments(); | 4270 ZoneList<Expression*>* args = expr->arguments(); |
4148 DCHECK(args->length() >= 2); | 4271 DCHECK(args->length() >= 2); |
4149 | 4272 |
4150 int arg_count = args->length() - 2; // 2 ~ receiver and function. | 4273 int arg_count = args->length() - 2; // 2 ~ receiver and function. |
4151 for (int i = 0; i < arg_count + 1; i++) { | 4274 for (int i = 0; i < arg_count + 1; i++) { |
4152 VisitForStackValue(args->at(i)); | 4275 VisitForStackValue(args->at(i)); |
4153 } | 4276 } |
(...skipping 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5457 DCHECK(interrupt_address == | 5580 DCHECK(interrupt_address == |
5458 isolate->builtins()->OsrAfterStackCheck()->entry()); | 5581 isolate->builtins()->OsrAfterStackCheck()->entry()); |
5459 return OSR_AFTER_STACK_CHECK; | 5582 return OSR_AFTER_STACK_CHECK; |
5460 } | 5583 } |
5461 | 5584 |
5462 | 5585 |
5463 } // namespace internal | 5586 } // namespace internal |
5464 } // namespace v8 | 5587 } // namespace v8 |
5465 | 5588 |
5466 #endif // V8_TARGET_ARCH_ARM | 5589 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |