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_X87 | 7 #if V8_TARGET_ARCH_X87 |
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 1789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1800 : KEYED_PROPERTY; | 1800 : KEYED_PROPERTY; |
1801 } | 1801 } |
1802 | 1802 |
1803 // Evaluate LHS expression. | 1803 // Evaluate LHS expression. |
1804 switch (assign_type) { | 1804 switch (assign_type) { |
1805 case VARIABLE: | 1805 case VARIABLE: |
1806 // Nothing to do here. | 1806 // Nothing to do here. |
1807 break; | 1807 break; |
1808 case NAMED_PROPERTY: | 1808 case NAMED_PROPERTY: |
1809 if (expr->is_compound()) { | 1809 if (expr->is_compound()) { |
1810 // We need the receiver both on the stack and in edx. | 1810 // We need the receiver both on the stack and in the register. |
1811 VisitForStackValue(property->obj()); | 1811 VisitForStackValue(property->obj()); |
1812 __ mov(edx, Operand(esp, 0)); | 1812 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); |
1813 } else { | 1813 } else { |
1814 VisitForStackValue(property->obj()); | 1814 VisitForStackValue(property->obj()); |
1815 } | 1815 } |
1816 break; | 1816 break; |
1817 case KEYED_PROPERTY: { | 1817 case KEYED_PROPERTY: { |
1818 if (expr->is_compound()) { | 1818 if (expr->is_compound()) { |
1819 VisitForStackValue(property->obj()); | 1819 VisitForStackValue(property->obj()); |
1820 VisitForStackValue(property->key()); | 1820 VisitForStackValue(property->key()); |
1821 __ mov(edx, Operand(esp, kPointerSize)); // Object. | 1821 __ mov(LoadIC::ReceiverRegister(), Operand(esp, kPointerSize)); |
1822 __ mov(ecx, Operand(esp, 0)); // Key. | 1822 __ mov(LoadIC::NameRegister(), Operand(esp, 0)); |
1823 } else { | 1823 } else { |
1824 VisitForStackValue(property->obj()); | 1824 VisitForStackValue(property->obj()); |
1825 VisitForStackValue(property->key()); | 1825 VisitForStackValue(property->key()); |
1826 } | 1826 } |
1827 break; | 1827 break; |
1828 } | 1828 } |
1829 } | 1829 } |
1830 | 1830 |
1831 // For compound assignments we need another deoptimization point after the | 1831 // For compound assignments we need another deoptimization point after the |
1832 // variable/property load. | 1832 // variable/property load. |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1952 | 1952 |
1953 case Yield::DELEGATING: { | 1953 case Yield::DELEGATING: { |
1954 VisitForStackValue(expr->generator_object()); | 1954 VisitForStackValue(expr->generator_object()); |
1955 | 1955 |
1956 // Initial stack layout is as follows: | 1956 // Initial stack layout is as follows: |
1957 // [sp + 1 * kPointerSize] iter | 1957 // [sp + 1 * kPointerSize] iter |
1958 // [sp + 0 * kPointerSize] g | 1958 // [sp + 0 * kPointerSize] g |
1959 | 1959 |
1960 Label l_catch, l_try, l_suspend, l_continuation, l_resume; | 1960 Label l_catch, l_try, l_suspend, l_continuation, l_resume; |
1961 Label l_next, l_call, l_loop; | 1961 Label l_next, l_call, l_loop; |
| 1962 Register load_receiver = LoadIC::ReceiverRegister(); |
| 1963 Register load_name = LoadIC::NameRegister(); |
| 1964 |
1962 // Initial send value is undefined. | 1965 // Initial send value is undefined. |
1963 __ mov(eax, isolate()->factory()->undefined_value()); | 1966 __ mov(eax, isolate()->factory()->undefined_value()); |
1964 __ jmp(&l_next); | 1967 __ jmp(&l_next); |
1965 | 1968 |
1966 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 1969 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } |
1967 __ bind(&l_catch); | 1970 __ bind(&l_catch); |
1968 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | 1971 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
1969 __ mov(ecx, isolate()->factory()->throw_string()); // "throw" | 1972 __ mov(load_name, isolate()->factory()->throw_string()); // "throw" |
1970 __ push(ecx); // "throw" | 1973 __ push(load_name); // "throw" |
1971 __ push(Operand(esp, 2 * kPointerSize)); // iter | 1974 __ push(Operand(esp, 2 * kPointerSize)); // iter |
1972 __ push(eax); // exception | 1975 __ push(eax); // exception |
1973 __ jmp(&l_call); | 1976 __ jmp(&l_call); |
1974 | 1977 |
1975 // try { received = %yield result } | 1978 // try { received = %yield result } |
1976 // Shuffle the received result above a try handler and yield it without | 1979 // Shuffle the received result above a try handler and yield it without |
1977 // re-boxing. | 1980 // re-boxing. |
1978 __ bind(&l_try); | 1981 __ bind(&l_try); |
1979 __ pop(eax); // result | 1982 __ pop(eax); // result |
1980 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 1983 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
1981 const int handler_size = StackHandlerConstants::kSize; | 1984 const int handler_size = StackHandlerConstants::kSize; |
1982 __ push(eax); // result | 1985 __ push(eax); // result |
(...skipping 13 matching lines...) Expand all Loading... |
1996 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1999 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
1997 __ mov(context_register(), | 2000 __ mov(context_register(), |
1998 Operand(ebp, StandardFrameConstants::kContextOffset)); | 2001 Operand(ebp, StandardFrameConstants::kContextOffset)); |
1999 __ pop(eax); // result | 2002 __ pop(eax); // result |
2000 EmitReturnSequence(); | 2003 EmitReturnSequence(); |
2001 __ bind(&l_resume); // received in eax | 2004 __ bind(&l_resume); // received in eax |
2002 __ PopTryHandler(); | 2005 __ PopTryHandler(); |
2003 | 2006 |
2004 // receiver = iter; f = iter.next; arg = received; | 2007 // receiver = iter; f = iter.next; arg = received; |
2005 __ bind(&l_next); | 2008 __ bind(&l_next); |
2006 Register keyedload_receiver = KeyedLoadIC::ReceiverRegister(); | |
2007 Register keyedload_name = KeyedLoadIC::NameRegister(); | |
2008 ASSERT(keyedload_receiver.is(edx)); | |
2009 ASSERT(keyedload_name.is(ecx)); | |
2010 | 2009 |
2011 __ mov(keyedload_name, | 2010 __ mov(load_name, isolate()->factory()->next_string()); |
2012 isolate()->factory()->next_string()); // "next" | 2011 __ push(load_name); // "next" |
2013 __ push(keyedload_name); | 2012 __ push(Operand(esp, 2 * kPointerSize)); // iter |
2014 __ push(Operand(esp, 2 * kPointerSize)); // iter | 2013 __ push(eax); // received |
2015 __ push(eax); // received | |
2016 | 2014 |
2017 // result = receiver[f](arg); | 2015 // result = receiver[f](arg); |
2018 __ bind(&l_call); | 2016 __ bind(&l_call); |
2019 __ mov(keyedload_receiver, Operand(esp, kPointerSize)); | 2017 __ mov(load_receiver, Operand(esp, kPointerSize)); |
2020 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2018 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2021 CallIC(ic, TypeFeedbackId::None()); | 2019 CallIC(ic, TypeFeedbackId::None()); |
2022 __ mov(edi, eax); | 2020 __ mov(edi, eax); |
2023 __ mov(Operand(esp, 2 * kPointerSize), edi); | 2021 __ mov(Operand(esp, 2 * kPointerSize), edi); |
2024 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); | 2022 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); |
2025 __ CallStub(&stub); | 2023 __ CallStub(&stub); |
2026 | 2024 |
2027 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2025 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2028 __ Drop(1); // The function is still on the stack; drop it. | 2026 __ Drop(1); // The function is still on the stack; drop it. |
2029 | 2027 |
2030 // if (!result.done) goto l_try; | 2028 // if (!result.done) goto l_try; |
2031 __ bind(&l_loop); | 2029 __ bind(&l_loop); |
2032 __ push(eax); // save result | 2030 __ push(eax); // save result |
2033 Register load_receiver = LoadIC::ReceiverRegister(); | 2031 __ Move(load_receiver, eax); // result |
2034 Register load_name = LoadIC::NameRegister(); | |
2035 ASSERT(load_receiver.is(edx)); | |
2036 ASSERT(load_name.is(ecx)); | |
2037 __ mov(load_receiver, eax); // result | |
2038 __ mov(load_name, | 2032 __ mov(load_name, |
2039 isolate()->factory()->done_string()); // "done" | 2033 isolate()->factory()->done_string()); // "done" |
2040 CallLoadIC(NOT_CONTEXTUAL); // result.done in eax | 2034 CallLoadIC(NOT_CONTEXTUAL); // result.done in eax |
2041 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 2035 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
2042 CallIC(bool_ic); | 2036 CallIC(bool_ic); |
2043 __ test(eax, eax); | 2037 __ test(eax, eax); |
2044 __ j(zero, &l_try); | 2038 __ j(zero, &l_try); |
2045 | 2039 |
2046 // result.value | 2040 // result.value |
2047 __ pop(load_receiver); // result | 2041 __ pop(load_receiver); // result |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2497 context()->Plug(eax); | 2491 context()->Plug(eax); |
2498 } | 2492 } |
2499 | 2493 |
2500 | 2494 |
2501 void FullCodeGenerator::VisitProperty(Property* expr) { | 2495 void FullCodeGenerator::VisitProperty(Property* expr) { |
2502 Comment cmnt(masm_, "[ Property"); | 2496 Comment cmnt(masm_, "[ Property"); |
2503 Expression* key = expr->key(); | 2497 Expression* key = expr->key(); |
2504 | 2498 |
2505 if (key->IsPropertyName()) { | 2499 if (key->IsPropertyName()) { |
2506 VisitForAccumulatorValue(expr->obj()); | 2500 VisitForAccumulatorValue(expr->obj()); |
2507 __ mov(LoadIC::ReceiverRegister(), result_register()); | 2501 __ Move(LoadIC::ReceiverRegister(), result_register()); |
2508 EmitNamedPropertyLoad(expr); | 2502 EmitNamedPropertyLoad(expr); |
2509 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2503 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
2510 context()->Plug(eax); | 2504 context()->Plug(eax); |
2511 } else { | 2505 } else { |
2512 VisitForStackValue(expr->obj()); | 2506 VisitForStackValue(expr->obj()); |
2513 VisitForAccumulatorValue(expr->key()); | 2507 VisitForAccumulatorValue(expr->key()); |
2514 __ pop(KeyedLoadIC::ReceiverRegister()); // Object. | 2508 __ pop(LoadIC::ReceiverRegister()); // Object. |
2515 __ mov(KeyedLoadIC::NameRegister(), result_register()); // Key. | 2509 __ Move(LoadIC::NameRegister(), result_register()); // Key. |
2516 EmitKeyedPropertyLoad(expr); | 2510 EmitKeyedPropertyLoad(expr); |
2517 context()->Plug(eax); | 2511 context()->Plug(eax); |
2518 } | 2512 } |
2519 } | 2513 } |
2520 | 2514 |
2521 | 2515 |
2522 void FullCodeGenerator::CallIC(Handle<Code> code, | 2516 void FullCodeGenerator::CallIC(Handle<Code> code, |
2523 TypeFeedbackId ast_id) { | 2517 TypeFeedbackId ast_id) { |
2524 ic_total_count_++; | 2518 ic_total_count_++; |
2525 __ call(code, RelocInfo::CODE_TARGET, ast_id); | 2519 __ call(code, RelocInfo::CODE_TARGET, ast_id); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2560 // Code common for calls using the IC. | 2554 // Code common for calls using the IC. |
2561 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, | 2555 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
2562 Expression* key) { | 2556 Expression* key) { |
2563 // Load the key. | 2557 // Load the key. |
2564 VisitForAccumulatorValue(key); | 2558 VisitForAccumulatorValue(key); |
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 __ mov(KeyedLoadIC::ReceiverRegister(), Operand(esp, 0)); | 2564 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); |
2571 // Move the key into the right register for the keyed load IC. | 2565 __ mov(LoadIC::NameRegister(), eax); |
2572 __ mov(KeyedLoadIC::NameRegister(), eax); | |
2573 EmitKeyedPropertyLoad(callee->AsProperty()); | 2566 EmitKeyedPropertyLoad(callee->AsProperty()); |
2574 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2567 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2575 | 2568 |
2576 // Push the target function under the receiver. | 2569 // Push the target function under the receiver. |
2577 __ push(Operand(esp, 0)); | 2570 __ push(Operand(esp, 0)); |
2578 __ mov(Operand(esp, kPointerSize), eax); | 2571 __ mov(Operand(esp, kPointerSize), eax); |
2579 | 2572 |
2580 EmitCall(expr, CallIC::METHOD); | 2573 EmitCall(expr, CallIC::METHOD); |
2581 } | 2574 } |
2582 | 2575 |
(...skipping 1618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4201 if (assign_type == VARIABLE) { | 4194 if (assign_type == VARIABLE) { |
4202 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 4195 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); |
4203 AccumulatorValueContext context(this); | 4196 AccumulatorValueContext context(this); |
4204 EmitVariableLoad(expr->expression()->AsVariableProxy()); | 4197 EmitVariableLoad(expr->expression()->AsVariableProxy()); |
4205 } else { | 4198 } else { |
4206 // Reserve space for result of postfix operation. | 4199 // Reserve space for result of postfix operation. |
4207 if (expr->is_postfix() && !context()->IsEffect()) { | 4200 if (expr->is_postfix() && !context()->IsEffect()) { |
4208 __ push(Immediate(Smi::FromInt(0))); | 4201 __ push(Immediate(Smi::FromInt(0))); |
4209 } | 4202 } |
4210 if (assign_type == NAMED_PROPERTY) { | 4203 if (assign_type == NAMED_PROPERTY) { |
4211 // Put the object both on the stack and in edx. | 4204 // Put the object both on the stack and in the register. |
4212 VisitForAccumulatorValue(prop->obj()); | 4205 VisitForStackValue(prop->obj()); |
4213 ASSERT(!eax.is(LoadIC::ReceiverRegister())); | 4206 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); |
4214 __ push(eax); | |
4215 __ mov(LoadIC::ReceiverRegister(), eax); | |
4216 EmitNamedPropertyLoad(prop); | 4207 EmitNamedPropertyLoad(prop); |
4217 } else { | 4208 } else { |
4218 VisitForStackValue(prop->obj()); | 4209 VisitForStackValue(prop->obj()); |
4219 VisitForStackValue(prop->key()); | 4210 VisitForStackValue(prop->key()); |
4220 __ mov(KeyedLoadIC::ReceiverRegister(), | 4211 __ mov(LoadIC::ReceiverRegister(), |
4221 Operand(esp, kPointerSize)); // Object. | 4212 Operand(esp, kPointerSize)); // Object. |
4222 __ mov(KeyedLoadIC::NameRegister(), Operand(esp, 0)); // Key. | 4213 __ mov(LoadIC::NameRegister(), Operand(esp, 0)); // Key. |
4223 EmitKeyedPropertyLoad(prop); | 4214 EmitKeyedPropertyLoad(prop); |
4224 } | 4215 } |
4225 } | 4216 } |
4226 | 4217 |
4227 // We need a second deoptimization point after loading the value | 4218 // We need a second deoptimization point after loading the value |
4228 // in case evaluating the property load my have a side effect. | 4219 // in case evaluating the property load my have a side effect. |
4229 if (assign_type == VARIABLE) { | 4220 if (assign_type == VARIABLE) { |
4230 PrepareForBailout(expr->expression(), TOS_REG); | 4221 PrepareForBailout(expr->expression(), TOS_REG); |
4231 } else { | 4222 } else { |
4232 PrepareForBailoutForId(prop->LoadId(), TOS_REG); | 4223 PrepareForBailoutForId(prop->LoadId(), TOS_REG); |
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4804 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4795 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
4805 Assembler::target_address_at(call_target_address, | 4796 Assembler::target_address_at(call_target_address, |
4806 unoptimized_code)); | 4797 unoptimized_code)); |
4807 return OSR_AFTER_STACK_CHECK; | 4798 return OSR_AFTER_STACK_CHECK; |
4808 } | 4799 } |
4809 | 4800 |
4810 | 4801 |
4811 } } // namespace v8::internal | 4802 } } // namespace v8::internal |
4812 | 4803 |
4813 #endif // V8_TARGET_ARCH_X87 | 4804 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |