| 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_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 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 1826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1837 : KEYED_PROPERTY; | 1837 : KEYED_PROPERTY; |
| 1838 } | 1838 } |
| 1839 | 1839 |
| 1840 // Evaluate LHS expression. | 1840 // Evaluate LHS expression. |
| 1841 switch (assign_type) { | 1841 switch (assign_type) { |
| 1842 case VARIABLE: | 1842 case VARIABLE: |
| 1843 // Nothing to do here. | 1843 // Nothing to do here. |
| 1844 break; | 1844 break; |
| 1845 case NAMED_PROPERTY: | 1845 case NAMED_PROPERTY: |
| 1846 if (expr->is_compound()) { | 1846 if (expr->is_compound()) { |
| 1847 // We need the receiver both on the stack and in the accumulator. | 1847 // We need the receiver both on the stack and in the register. |
| 1848 VisitForAccumulatorValue(property->obj()); | 1848 VisitForStackValue(property->obj()); |
| 1849 __ Push(result_register()); | 1849 __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0)); |
| 1850 } else { | 1850 } else { |
| 1851 VisitForStackValue(property->obj()); | 1851 VisitForStackValue(property->obj()); |
| 1852 } | 1852 } |
| 1853 break; | 1853 break; |
| 1854 case KEYED_PROPERTY: { | 1854 case KEYED_PROPERTY: { |
| 1855 if (expr->is_compound()) { | 1855 if (expr->is_compound()) { |
| 1856 VisitForStackValue(property->obj()); | 1856 VisitForStackValue(property->obj()); |
| 1857 VisitForAccumulatorValue(property->key()); | 1857 VisitForStackValue(property->key()); |
| 1858 __ movp(rdx, Operand(rsp, 0)); | 1858 __ movp(LoadIC::ReceiverRegister(), Operand(rsp, kPointerSize)); |
| 1859 __ Push(rax); | 1859 __ movp(LoadIC::NameRegister(), Operand(rsp, 0)); |
| 1860 } else { | 1860 } else { |
| 1861 VisitForStackValue(property->obj()); | 1861 VisitForStackValue(property->obj()); |
| 1862 VisitForStackValue(property->key()); | 1862 VisitForStackValue(property->key()); |
| 1863 } | 1863 } |
| 1864 break; | 1864 break; |
| 1865 } | 1865 } |
| 1866 } | 1866 } |
| 1867 | 1867 |
| 1868 // For compound assignments we need another deoptimization point after the | 1868 // For compound assignments we need another deoptimization point after the |
| 1869 // variable/property load. | 1869 // variable/property load. |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1990 | 1990 |
| 1991 case Yield::DELEGATING: { | 1991 case Yield::DELEGATING: { |
| 1992 VisitForStackValue(expr->generator_object()); | 1992 VisitForStackValue(expr->generator_object()); |
| 1993 | 1993 |
| 1994 // Initial stack layout is as follows: | 1994 // Initial stack layout is as follows: |
| 1995 // [sp + 1 * kPointerSize] iter | 1995 // [sp + 1 * kPointerSize] iter |
| 1996 // [sp + 0 * kPointerSize] g | 1996 // [sp + 0 * kPointerSize] g |
| 1997 | 1997 |
| 1998 Label l_catch, l_try, l_suspend, l_continuation, l_resume; | 1998 Label l_catch, l_try, l_suspend, l_continuation, l_resume; |
| 1999 Label l_next, l_call, l_loop; | 1999 Label l_next, l_call, l_loop; |
| 2000 Register load_receiver = LoadIC::ReceiverRegister(); |
| 2001 Register load_name = LoadIC::NameRegister(); |
| 2002 |
| 2000 // Initial send value is undefined. | 2003 // Initial send value is undefined. |
| 2001 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 2004 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 2002 __ jmp(&l_next); | 2005 __ jmp(&l_next); |
| 2003 | 2006 |
| 2004 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 2007 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } |
| 2005 __ bind(&l_catch); | 2008 __ bind(&l_catch); |
| 2006 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | 2009 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
| 2007 __ LoadRoot(rcx, Heap::kthrow_stringRootIndex); // "throw" | 2010 __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw" |
| 2008 __ Push(rcx); | 2011 __ Push(load_name); |
| 2009 __ Push(Operand(rsp, 2 * kPointerSize)); // iter | 2012 __ Push(Operand(rsp, 2 * kPointerSize)); // iter |
| 2010 __ Push(rax); // exception | 2013 __ Push(rax); // exception |
| 2011 __ jmp(&l_call); | 2014 __ jmp(&l_call); |
| 2012 | 2015 |
| 2013 // try { received = %yield result } | 2016 // try { received = %yield result } |
| 2014 // Shuffle the received result above a try handler and yield it without | 2017 // Shuffle the received result above a try handler and yield it without |
| 2015 // re-boxing. | 2018 // re-boxing. |
| 2016 __ bind(&l_try); | 2019 __ bind(&l_try); |
| 2017 __ Pop(rax); // result | 2020 __ Pop(rax); // result |
| 2018 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 2021 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
| 2019 const int handler_size = StackHandlerConstants::kSize; | 2022 const int handler_size = StackHandlerConstants::kSize; |
| 2020 __ Push(rax); // result | 2023 __ Push(rax); // result |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2035 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2038 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 2036 __ movp(context_register(), | 2039 __ movp(context_register(), |
| 2037 Operand(rbp, StandardFrameConstants::kContextOffset)); | 2040 Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2038 __ Pop(rax); // result | 2041 __ Pop(rax); // result |
| 2039 EmitReturnSequence(); | 2042 EmitReturnSequence(); |
| 2040 __ bind(&l_resume); // received in rax | 2043 __ bind(&l_resume); // received in rax |
| 2041 __ PopTryHandler(); | 2044 __ PopTryHandler(); |
| 2042 | 2045 |
| 2043 // receiver = iter; f = 'next'; arg = received; | 2046 // receiver = iter; f = 'next'; arg = received; |
| 2044 __ bind(&l_next); | 2047 __ bind(&l_next); |
| 2045 Register keyedload_receiver = KeyedLoadIC::ReceiverRegister(); | |
| 2046 Register keyedload_name = KeyedLoadIC::NameRegister(); | |
| 2047 ASSERT(keyedload_receiver.is(rdx)); | |
| 2048 ASSERT(keyedload_name.is(rax)); | |
| 2049 | 2048 |
| 2050 __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next" | 2049 __ LoadRoot(load_name, Heap::knext_stringRootIndex); |
| 2051 __ Push(rcx); | 2050 __ Push(load_name); // "next" |
| 2052 __ Push(Operand(rsp, 2 * kPointerSize)); // iter | 2051 __ Push(Operand(rsp, 2 * kPointerSize)); // iter |
| 2053 __ Push(rax); // received | 2052 __ Push(rax); // received |
| 2054 | 2053 |
| 2055 // result = receiver[f](arg); | 2054 // result = receiver[f](arg); |
| 2056 __ bind(&l_call); | 2055 __ bind(&l_call); |
| 2057 __ movp(keyedload_receiver, Operand(rsp, kPointerSize)); | 2056 __ movp(load_receiver, Operand(rsp, kPointerSize)); |
| 2058 __ movp(keyedload_name, Operand(rsp, 2 * kPointerSize)); | |
| 2059 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2057 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2060 CallIC(ic, TypeFeedbackId::None()); | 2058 CallIC(ic, TypeFeedbackId::None()); |
| 2061 __ movp(rdi, rax); | 2059 __ movp(rdi, rax); |
| 2062 __ movp(Operand(rsp, 2 * kPointerSize), rdi); | 2060 __ movp(Operand(rsp, 2 * kPointerSize), rdi); |
| 2063 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); | 2061 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); |
| 2064 __ CallStub(&stub); | 2062 __ CallStub(&stub); |
| 2065 | 2063 |
| 2066 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2064 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2067 __ Drop(1); // The function is still on the stack; drop it. | 2065 __ Drop(1); // The function is still on the stack; drop it. |
| 2068 | 2066 |
| 2069 // if (!result.done) goto l_try; | 2067 // if (!result.done) goto l_try; |
| 2070 __ bind(&l_loop); | 2068 __ bind(&l_loop); |
| 2071 Register load_receiver = LoadIC::ReceiverRegister(); | 2069 __ Move(load_receiver, rax); |
| 2072 Register load_name = LoadIC::NameRegister(); | |
| 2073 ASSERT(load_receiver.is(rax)); | |
| 2074 ASSERT(load_name.is(rcx)); | |
| 2075 | |
| 2076 __ Push(load_receiver); // save result | 2070 __ Push(load_receiver); // save result |
| 2077 __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" | 2071 __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" |
| 2078 CallLoadIC(NOT_CONTEXTUAL); // rax=result.done | 2072 CallLoadIC(NOT_CONTEXTUAL); // rax=result.done |
| 2079 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 2073 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
| 2080 CallIC(bool_ic); | 2074 CallIC(bool_ic); |
| 2081 __ testp(result_register(), result_register()); | 2075 __ testp(result_register(), result_register()); |
| 2082 __ j(zero, &l_try); | 2076 __ j(zero, &l_try); |
| 2083 | 2077 |
| 2084 // result.value | 2078 // result.value |
| 2085 __ Pop(load_receiver); // result | 2079 __ Pop(load_receiver); // result |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2496 context()->Plug(rax); | 2490 context()->Plug(rax); |
| 2497 } | 2491 } |
| 2498 | 2492 |
| 2499 | 2493 |
| 2500 void FullCodeGenerator::VisitProperty(Property* expr) { | 2494 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 2501 Comment cmnt(masm_, "[ Property"); | 2495 Comment cmnt(masm_, "[ Property"); |
| 2502 Expression* key = expr->key(); | 2496 Expression* key = expr->key(); |
| 2503 | 2497 |
| 2504 if (key->IsPropertyName()) { | 2498 if (key->IsPropertyName()) { |
| 2505 VisitForAccumulatorValue(expr->obj()); | 2499 VisitForAccumulatorValue(expr->obj()); |
| 2506 ASSERT(rax.is(LoadIC::ReceiverRegister())); | 2500 ASSERT(!rax.is(LoadIC::ReceiverRegister())); |
| 2501 __ movp(LoadIC::ReceiverRegister(), rax); |
| 2507 EmitNamedPropertyLoad(expr); | 2502 EmitNamedPropertyLoad(expr); |
| 2508 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2503 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
| 2509 context()->Plug(rax); | 2504 context()->Plug(rax); |
| 2510 } else { | 2505 } else { |
| 2511 VisitForStackValue(expr->obj()); | 2506 VisitForStackValue(expr->obj()); |
| 2512 VisitForAccumulatorValue(expr->key()); | 2507 VisitForAccumulatorValue(expr->key()); |
| 2513 ASSERT(rax.is(KeyedLoadIC::NameRegister())); | 2508 __ Move(LoadIC::NameRegister(), rax); |
| 2514 __ Pop(KeyedLoadIC::ReceiverRegister()); | 2509 __ Pop(LoadIC::ReceiverRegister()); |
| 2515 EmitKeyedPropertyLoad(expr); | 2510 EmitKeyedPropertyLoad(expr); |
| 2516 context()->Plug(rax); | 2511 context()->Plug(rax); |
| 2517 } | 2512 } |
| 2518 } | 2513 } |
| 2519 | 2514 |
| 2520 | 2515 |
| 2521 void FullCodeGenerator::CallIC(Handle<Code> code, | 2516 void FullCodeGenerator::CallIC(Handle<Code> code, |
| 2522 TypeFeedbackId ast_id) { | 2517 TypeFeedbackId ast_id) { |
| 2523 ic_total_count_++; | 2518 ic_total_count_++; |
| 2524 __ call(code, RelocInfo::CODE_TARGET, ast_id); | 2519 __ call(code, RelocInfo::CODE_TARGET, ast_id); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2554 | 2549 |
| 2555 EmitCall(expr, call_type); | 2550 EmitCall(expr, call_type); |
| 2556 } | 2551 } |
| 2557 | 2552 |
| 2558 | 2553 |
| 2559 // Common code for calls using the IC. | 2554 // Common code for calls using the IC. |
| 2560 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, | 2555 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
| 2561 Expression* key) { | 2556 Expression* key) { |
| 2562 // Load the key. | 2557 // Load the key. |
| 2563 VisitForAccumulatorValue(key); | 2558 VisitForAccumulatorValue(key); |
| 2564 ASSERT(rax.is(KeyedLoadIC::NameRegister())); | |
| 2565 | 2559 |
| 2566 Expression* callee = expr->expression(); | 2560 Expression* callee = expr->expression(); |
| 2567 | 2561 |
| 2568 // Load the function from the receiver. | 2562 // Load the function from the receiver. |
| 2569 ASSERT(callee->IsProperty()); | 2563 ASSERT(callee->IsProperty()); |
| 2570 __ movp(KeyedLoadIC::ReceiverRegister(), Operand(rsp, 0)); | 2564 __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0)); |
| 2565 __ Move(LoadIC::NameRegister(), rax); |
| 2571 EmitKeyedPropertyLoad(callee->AsProperty()); | 2566 EmitKeyedPropertyLoad(callee->AsProperty()); |
| 2572 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2567 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2573 | 2568 |
| 2574 // Push the target function under the receiver. | 2569 // Push the target function under the receiver. |
| 2575 __ Push(Operand(rsp, 0)); | 2570 __ Push(Operand(rsp, 0)); |
| 2576 __ movp(Operand(rsp, kPointerSize), rax); | 2571 __ movp(Operand(rsp, kPointerSize), rax); |
| 2577 | 2572 |
| 2578 EmitCall(expr, CallIC::METHOD); | 2573 EmitCall(expr, CallIC::METHOD); |
| 2579 } | 2574 } |
| 2580 | 2575 |
| (...skipping 1636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4217 if (assign_type == VARIABLE) { | 4212 if (assign_type == VARIABLE) { |
| 4218 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 4213 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); |
| 4219 AccumulatorValueContext context(this); | 4214 AccumulatorValueContext context(this); |
| 4220 EmitVariableLoad(expr->expression()->AsVariableProxy()); | 4215 EmitVariableLoad(expr->expression()->AsVariableProxy()); |
| 4221 } else { | 4216 } else { |
| 4222 // Reserve space for result of postfix operation. | 4217 // Reserve space for result of postfix operation. |
| 4223 if (expr->is_postfix() && !context()->IsEffect()) { | 4218 if (expr->is_postfix() && !context()->IsEffect()) { |
| 4224 __ Push(Smi::FromInt(0)); | 4219 __ Push(Smi::FromInt(0)); |
| 4225 } | 4220 } |
| 4226 if (assign_type == NAMED_PROPERTY) { | 4221 if (assign_type == NAMED_PROPERTY) { |
| 4227 VisitForAccumulatorValue(prop->obj()); | 4222 VisitForStackValue(prop->obj()); |
| 4228 ASSERT(rax.is(LoadIC::ReceiverRegister())); | 4223 __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0)); |
| 4229 __ Push(rax); // Copy of receiver, needed for later store. | |
| 4230 EmitNamedPropertyLoad(prop); | 4224 EmitNamedPropertyLoad(prop); |
| 4231 } else { | 4225 } else { |
| 4232 VisitForStackValue(prop->obj()); | 4226 VisitForStackValue(prop->obj()); |
| 4233 VisitForAccumulatorValue(prop->key()); | 4227 VisitForStackValue(prop->key()); |
| 4234 ASSERT(rax.is(KeyedLoadIC::NameRegister())); | |
| 4235 // Leave receiver on stack | 4228 // Leave receiver on stack |
| 4236 __ movp(KeyedLoadIC::ReceiverRegister(), Operand(rsp, 0)); | 4229 __ movp(LoadIC::ReceiverRegister(), Operand(rsp, kPointerSize)); |
| 4237 // Copy of key, needed for later store. | 4230 // Copy of key, needed for later store. |
| 4238 __ Push(KeyedLoadIC::NameRegister()); | 4231 __ movp(LoadIC::NameRegister(), Operand(rsp, 0)); |
| 4239 EmitKeyedPropertyLoad(prop); | 4232 EmitKeyedPropertyLoad(prop); |
| 4240 } | 4233 } |
| 4241 } | 4234 } |
| 4242 | 4235 |
| 4243 // We need a second deoptimization point after loading the value | 4236 // We need a second deoptimization point after loading the value |
| 4244 // in case evaluating the property load my have a side effect. | 4237 // in case evaluating the property load my have a side effect. |
| 4245 if (assign_type == VARIABLE) { | 4238 if (assign_type == VARIABLE) { |
| 4246 PrepareForBailout(expr->expression(), TOS_REG); | 4239 PrepareForBailout(expr->expression(), TOS_REG); |
| 4247 } else { | 4240 } else { |
| 4248 PrepareForBailoutForId(prop->LoadId(), TOS_REG); | 4241 PrepareForBailoutForId(prop->LoadId(), TOS_REG); |
| (...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4819 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4812 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
| 4820 Assembler::target_address_at(call_target_address, | 4813 Assembler::target_address_at(call_target_address, |
| 4821 unoptimized_code)); | 4814 unoptimized_code)); |
| 4822 return OSR_AFTER_STACK_CHECK; | 4815 return OSR_AFTER_STACK_CHECK; |
| 4823 } | 4816 } |
| 4824 | 4817 |
| 4825 | 4818 |
| 4826 } } // namespace v8::internal | 4819 } } // namespace v8::internal |
| 4827 | 4820 |
| 4828 #endif // V8_TARGET_ARCH_X64 | 4821 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |