| 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 |