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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 1840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1851 : KEYED_PROPERTY; | 1851 : KEYED_PROPERTY; |
1852 } | 1852 } |
1853 | 1853 |
1854 // Evaluate LHS expression. | 1854 // Evaluate LHS expression. |
1855 switch (assign_type) { | 1855 switch (assign_type) { |
1856 case VARIABLE: | 1856 case VARIABLE: |
1857 // Nothing to do here. | 1857 // Nothing to do here. |
1858 break; | 1858 break; |
1859 case NAMED_PROPERTY: | 1859 case NAMED_PROPERTY: |
1860 if (expr->is_compound()) { | 1860 if (expr->is_compound()) { |
1861 // We need the receiver both on the stack and in the accumulator. | 1861 // We need the receiver both on the stack and in the register. |
1862 VisitForAccumulatorValue(property->obj()); | 1862 VisitForStackValue(property->obj()); |
1863 __ Push(result_register()); | 1863 __ Peek(LoadIC::ReceiverRegister(), 0); |
1864 } else { | 1864 } else { |
1865 VisitForStackValue(property->obj()); | 1865 VisitForStackValue(property->obj()); |
1866 } | 1866 } |
1867 break; | 1867 break; |
1868 case KEYED_PROPERTY: | 1868 case KEYED_PROPERTY: |
1869 if (expr->is_compound()) { | 1869 if (expr->is_compound()) { |
1870 VisitForStackValue(property->obj()); | 1870 VisitForStackValue(property->obj()); |
1871 VisitForAccumulatorValue(property->key()); | 1871 VisitForStackValue(property->key()); |
1872 __ Peek(x1, 0); | 1872 __ Peek(LoadIC::ReceiverRegister(), 1 * kPointerSize); |
1873 __ Push(x0); | 1873 __ Peek(LoadIC::NameRegister(), 0); |
1874 } else { | 1874 } else { |
1875 VisitForStackValue(property->obj()); | 1875 VisitForStackValue(property->obj()); |
1876 VisitForStackValue(property->key()); | 1876 VisitForStackValue(property->key()); |
1877 } | 1877 } |
1878 break; | 1878 break; |
1879 } | 1879 } |
1880 | 1880 |
1881 // For compound assignments we need another deoptimization point after the | 1881 // For compound assignments we need another deoptimization point after the |
1882 // variable/property load. | 1882 // variable/property load. |
1883 if (expr->is_compound()) { | 1883 if (expr->is_compound()) { |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2253 context()->Plug(x0); | 2253 context()->Plug(x0); |
2254 } | 2254 } |
2255 | 2255 |
2256 | 2256 |
2257 void FullCodeGenerator::VisitProperty(Property* expr) { | 2257 void FullCodeGenerator::VisitProperty(Property* expr) { |
2258 Comment cmnt(masm_, "[ Property"); | 2258 Comment cmnt(masm_, "[ Property"); |
2259 Expression* key = expr->key(); | 2259 Expression* key = expr->key(); |
2260 | 2260 |
2261 if (key->IsPropertyName()) { | 2261 if (key->IsPropertyName()) { |
2262 VisitForAccumulatorValue(expr->obj()); | 2262 VisitForAccumulatorValue(expr->obj()); |
2263 ASSERT(x0.is(LoadIC::ReceiverRegister())); | 2263 __ Move(LoadIC::ReceiverRegister(), x0); |
2264 EmitNamedPropertyLoad(expr); | 2264 EmitNamedPropertyLoad(expr); |
2265 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2265 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
2266 context()->Plug(x0); | 2266 context()->Plug(x0); |
2267 } else { | 2267 } else { |
2268 VisitForStackValue(expr->obj()); | 2268 VisitForStackValue(expr->obj()); |
2269 VisitForAccumulatorValue(expr->key()); | 2269 VisitForAccumulatorValue(expr->key()); |
2270 ASSERT(x0.is(KeyedLoadIC::NameRegister())); | 2270 __ Move(LoadIC::NameRegister(), x0); |
2271 __ Pop(KeyedLoadIC::ReceiverRegister()); | 2271 __ Pop(LoadIC::ReceiverRegister()); |
2272 EmitKeyedPropertyLoad(expr); | 2272 EmitKeyedPropertyLoad(expr); |
2273 context()->Plug(x0); | 2273 context()->Plug(x0); |
2274 } | 2274 } |
2275 } | 2275 } |
2276 | 2276 |
2277 | 2277 |
2278 void FullCodeGenerator::CallIC(Handle<Code> code, | 2278 void FullCodeGenerator::CallIC(Handle<Code> code, |
2279 TypeFeedbackId ast_id) { | 2279 TypeFeedbackId ast_id) { |
2280 ic_total_count_++; | 2280 ic_total_count_++; |
2281 // All calls must have a predictable size in full-codegen code to ensure that | 2281 // All calls must have a predictable size in full-codegen code to ensure that |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2314 | 2314 |
2315 EmitCall(expr, call_type); | 2315 EmitCall(expr, call_type); |
2316 } | 2316 } |
2317 | 2317 |
2318 | 2318 |
2319 // Code common for calls using the IC. | 2319 // Code common for calls using the IC. |
2320 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, | 2320 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
2321 Expression* key) { | 2321 Expression* key) { |
2322 // Load the key. | 2322 // Load the key. |
2323 VisitForAccumulatorValue(key); | 2323 VisitForAccumulatorValue(key); |
2324 ASSERT(x0.is(KeyedLoadIC::NameRegister())); | |
2325 | 2324 |
2326 Expression* callee = expr->expression(); | 2325 Expression* callee = expr->expression(); |
2327 | 2326 |
2328 // Load the function from the receiver. | 2327 // Load the function from the receiver. |
2329 ASSERT(callee->IsProperty()); | 2328 ASSERT(callee->IsProperty()); |
2330 __ Peek(KeyedLoadIC::ReceiverRegister(), 0); | 2329 __ Peek(LoadIC::ReceiverRegister(), 0); |
| 2330 __ Move(LoadIC::NameRegister(), x0); |
2331 EmitKeyedPropertyLoad(callee->AsProperty()); | 2331 EmitKeyedPropertyLoad(callee->AsProperty()); |
2332 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2332 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2333 | 2333 |
2334 // Push the target function under the receiver. | 2334 // Push the target function under the receiver. |
2335 __ Pop(x10); | 2335 __ Pop(x10); |
2336 __ Push(x0, x10); | 2336 __ Push(x0, x10); |
2337 | 2337 |
2338 EmitCall(expr, CallIC::METHOD); | 2338 EmitCall(expr, CallIC::METHOD); |
2339 } | 2339 } |
2340 | 2340 |
(...skipping 1579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3920 if (assign_type == VARIABLE) { | 3920 if (assign_type == VARIABLE) { |
3921 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 3921 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); |
3922 AccumulatorValueContext context(this); | 3922 AccumulatorValueContext context(this); |
3923 EmitVariableLoad(expr->expression()->AsVariableProxy()); | 3923 EmitVariableLoad(expr->expression()->AsVariableProxy()); |
3924 } else { | 3924 } else { |
3925 // Reserve space for result of postfix operation. | 3925 // Reserve space for result of postfix operation. |
3926 if (expr->is_postfix() && !context()->IsEffect()) { | 3926 if (expr->is_postfix() && !context()->IsEffect()) { |
3927 __ Push(xzr); | 3927 __ Push(xzr); |
3928 } | 3928 } |
3929 if (assign_type == NAMED_PROPERTY) { | 3929 if (assign_type == NAMED_PROPERTY) { |
3930 // Put the object both on the stack and in the accumulator. | 3930 // Put the object both on the stack and in the register. |
3931 VisitForAccumulatorValue(prop->obj()); | 3931 VisitForStackValue(prop->obj()); |
3932 ASSERT(x0.is(LoadIC::ReceiverRegister())); | 3932 __ Peek(LoadIC::ReceiverRegister(), 0); |
3933 __ Push(LoadIC::ReceiverRegister()); | |
3934 EmitNamedPropertyLoad(prop); | 3933 EmitNamedPropertyLoad(prop); |
3935 } else { | 3934 } else { |
3936 // KEYED_PROPERTY | 3935 // KEYED_PROPERTY |
3937 VisitForStackValue(prop->obj()); | 3936 VisitForStackValue(prop->obj()); |
3938 VisitForAccumulatorValue(prop->key()); | 3937 VisitForStackValue(prop->key()); |
3939 ASSERT(x0.is(KeyedLoadIC::NameRegister())); | 3938 __ Peek(LoadIC::ReceiverRegister(), 1 * kPointerSize); |
3940 __ Peek(KeyedLoadIC::ReceiverRegister(), 0); | 3939 __ Peek(LoadIC::NameRegister(), 0); |
3941 __ Push(KeyedLoadIC::NameRegister()); | |
3942 EmitKeyedPropertyLoad(prop); | 3940 EmitKeyedPropertyLoad(prop); |
3943 } | 3941 } |
3944 } | 3942 } |
3945 | 3943 |
3946 // We need a second deoptimization point after loading the value | 3944 // We need a second deoptimization point after loading the value |
3947 // in case evaluating the property load my have a side effect. | 3945 // in case evaluating the property load my have a side effect. |
3948 if (assign_type == VARIABLE) { | 3946 if (assign_type == VARIABLE) { |
3949 PrepareForBailout(expr->expression(), TOS_REG); | 3947 PrepareForBailout(expr->expression(), TOS_REG); |
3950 } else { | 3948 } else { |
3951 PrepareForBailoutForId(prop->LoadId(), TOS_REG); | 3949 PrepareForBailoutForId(prop->LoadId(), TOS_REG); |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4382 | 4380 |
4383 case Yield::DELEGATING: { | 4381 case Yield::DELEGATING: { |
4384 VisitForStackValue(expr->generator_object()); | 4382 VisitForStackValue(expr->generator_object()); |
4385 | 4383 |
4386 // Initial stack layout is as follows: | 4384 // Initial stack layout is as follows: |
4387 // [sp + 1 * kPointerSize] iter | 4385 // [sp + 1 * kPointerSize] iter |
4388 // [sp + 0 * kPointerSize] g | 4386 // [sp + 0 * kPointerSize] g |
4389 | 4387 |
4390 Label l_catch, l_try, l_suspend, l_continuation, l_resume; | 4388 Label l_catch, l_try, l_suspend, l_continuation, l_resume; |
4391 Label l_next, l_call, l_loop; | 4389 Label l_next, l_call, l_loop; |
| 4390 Register load_receiver = LoadIC::ReceiverRegister(); |
| 4391 Register load_name = LoadIC::NameRegister(); |
| 4392 |
4392 // Initial send value is undefined. | 4393 // Initial send value is undefined. |
4393 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 4394 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
4394 __ B(&l_next); | 4395 __ B(&l_next); |
4395 | 4396 |
4396 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 4397 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } |
4397 __ Bind(&l_catch); | 4398 __ Bind(&l_catch); |
4398 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | 4399 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
4399 __ LoadRoot(x2, Heap::kthrow_stringRootIndex); // "throw" | 4400 __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw" |
4400 __ Peek(x3, 1 * kPointerSize); // iter | 4401 __ Peek(x3, 1 * kPointerSize); // iter |
4401 __ Push(x2, x3, x0); // "throw", iter, except | 4402 __ Push(load_name, x3, x0); // "throw", iter, except |
4402 __ B(&l_call); | 4403 __ B(&l_call); |
4403 | 4404 |
4404 // try { received = %yield result } | 4405 // try { received = %yield result } |
4405 // Shuffle the received result above a try handler and yield it without | 4406 // Shuffle the received result above a try handler and yield it without |
4406 // re-boxing. | 4407 // re-boxing. |
4407 __ Bind(&l_try); | 4408 __ Bind(&l_try); |
4408 __ Pop(x0); // result | 4409 __ Pop(x0); // result |
4409 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 4410 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
4410 const int handler_size = StackHandlerConstants::kSize; | 4411 const int handler_size = StackHandlerConstants::kSize; |
4411 __ Push(x0); // result | 4412 __ Push(x0); // result |
(...skipping 18 matching lines...) Expand all Loading... |
4430 kLRHasBeenSaved, kDontSaveFPRegs); | 4431 kLRHasBeenSaved, kDontSaveFPRegs); |
4431 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 4432 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
4432 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4433 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
4433 __ Pop(x0); // result | 4434 __ Pop(x0); // result |
4434 EmitReturnSequence(); | 4435 EmitReturnSequence(); |
4435 __ Bind(&l_resume); // received in x0 | 4436 __ Bind(&l_resume); // received in x0 |
4436 __ PopTryHandler(); | 4437 __ PopTryHandler(); |
4437 | 4438 |
4438 // receiver = iter; f = 'next'; arg = received; | 4439 // receiver = iter; f = 'next'; arg = received; |
4439 __ Bind(&l_next); | 4440 __ Bind(&l_next); |
4440 Register keyedload_receiver = KeyedLoadIC::ReceiverRegister(); | |
4441 Register keyedload_name = KeyedLoadIC::NameRegister(); | |
4442 ASSERT(keyedload_receiver.is(x1)); | |
4443 ASSERT(keyedload_name.is(x0)); | |
4444 | 4441 |
4445 __ LoadRoot(x2, Heap::knext_stringRootIndex); // "next" | 4442 __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next" |
4446 __ Peek(x3, 1 * kPointerSize); // iter | 4443 __ Peek(x3, 1 * kPointerSize); // iter |
4447 __ Push(x2, x3, x0); // "next", iter, received | 4444 __ Push(load_name, x3, x0); // "next", iter, received |
4448 | 4445 |
4449 // result = receiver[f](arg); | 4446 // result = receiver[f](arg); |
4450 __ Bind(&l_call); | 4447 __ Bind(&l_call); |
4451 __ Peek(keyedload_receiver, 1 * kPointerSize); | 4448 __ Peek(load_receiver, 1 * kPointerSize); |
4452 __ Peek(keyedload_name, 2 * kPointerSize); | 4449 __ Peek(load_name, 2 * kPointerSize); |
4453 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 4450 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
4454 CallIC(ic, TypeFeedbackId::None()); | 4451 CallIC(ic, TypeFeedbackId::None()); |
4455 __ Mov(x1, x0); | 4452 __ Mov(x1, x0); |
4456 __ Poke(x1, 2 * kPointerSize); | 4453 __ Poke(x1, 2 * kPointerSize); |
4457 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); | 4454 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); |
4458 __ CallStub(&stub); | 4455 __ CallStub(&stub); |
4459 | 4456 |
4460 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4457 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
4461 __ Drop(1); // The function is still on the stack; drop it. | 4458 __ Drop(1); // The function is still on the stack; drop it. |
4462 | 4459 |
4463 // if (!result.done) goto l_try; | 4460 // if (!result.done) goto l_try; |
4464 __ Bind(&l_loop); | 4461 __ Bind(&l_loop); |
4465 Register load_receiver = LoadIC::ReceiverRegister(); | 4462 __ Move(load_receiver, x0); |
4466 Register load_name = LoadIC::NameRegister(); | 4463 |
4467 ASSERT(load_receiver.is(x0)); | |
4468 ASSERT(load_name.is(x2)); | |
4469 __ Push(load_receiver); // save result | 4464 __ Push(load_receiver); // save result |
4470 __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" | 4465 __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" |
4471 CallLoadIC(NOT_CONTEXTUAL); // x0=result.done | 4466 CallLoadIC(NOT_CONTEXTUAL); // x0=result.done |
4472 // The ToBooleanStub argument (result.done) is in x0. | 4467 // The ToBooleanStub argument (result.done) is in x0. |
4473 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 4468 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
4474 CallIC(bool_ic); | 4469 CallIC(bool_ic); |
4475 __ Cbz(x0, &l_try); | 4470 __ Cbz(x0, &l_try); |
4476 | 4471 |
4477 // result.value | 4472 // result.value |
4478 __ Pop(load_receiver); // result | 4473 __ Pop(load_receiver); // result |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4899 return previous_; | 4894 return previous_; |
4900 } | 4895 } |
4901 | 4896 |
4902 | 4897 |
4903 #undef __ | 4898 #undef __ |
4904 | 4899 |
4905 | 4900 |
4906 } } // namespace v8::internal | 4901 } } // namespace v8::internal |
4907 | 4902 |
4908 #endif // V8_TARGET_ARCH_ARM64 | 4903 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |