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