| 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 "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_X87 |
| 8 | 8 |
| 9 #include "code-stubs.h" | 9 #include "code-stubs.h" |
| 10 #include "codegen.h" | 10 #include "codegen.h" |
| 11 #include "compiler.h" | 11 #include "compiler.h" |
| 12 #include "debug.h" | 12 #include "debug.h" |
| 13 #include "full-codegen.h" | 13 #include "full-codegen.h" |
| 14 #include "isolate-inl.h" | 14 #include "isolate-inl.h" |
| 15 #include "parser.h" | 15 #include "parser.h" |
| 16 #include "scopes.h" | 16 #include "scopes.h" |
| 17 #include "stub-cache.h" | 17 #include "stub-cache.h" |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 // return address on top of them. The actual argument count matches the | 104 // return address on top of them. The actual argument count matches the |
| 105 // formal parameter count expected by the function. | 105 // formal parameter count expected by the function. |
| 106 // | 106 // |
| 107 // The live registers are: | 107 // The live registers are: |
| 108 // o edi: the JS function object being called (i.e. ourselves) | 108 // o edi: the JS function object being called (i.e. ourselves) |
| 109 // o esi: our context | 109 // o esi: our context |
| 110 // o ebp: our caller's frame pointer | 110 // o ebp: our caller's frame pointer |
| 111 // o esp: stack pointer (pointing to return address) | 111 // o esp: stack pointer (pointing to return address) |
| 112 // | 112 // |
| 113 // The function builds a JS frame. Please see JavaScriptFrameConstants in | 113 // The function builds a JS frame. Please see JavaScriptFrameConstants in |
| 114 // frames-ia32.h for its layout. | 114 // frames-x87.h for its layout. |
| 115 void FullCodeGenerator::Generate() { | 115 void FullCodeGenerator::Generate() { |
| 116 CompilationInfo* info = info_; | 116 CompilationInfo* info = info_; |
| 117 handler_table_ = | 117 handler_table_ = |
| 118 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); | 118 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); |
| 119 | 119 |
| 120 profiling_counter_ = isolate()->factory()->NewCell( | 120 profiling_counter_ = isolate()->factory()->NewCell( |
| 121 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); | 121 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); |
| 122 SetFunctionPosition(function()); | 122 SetFunctionPosition(function()); |
| 123 Comment cmnt(masm_, "[ function compiled by full code generator"); | 123 Comment cmnt(masm_, "[ function compiled by full code generator"); |
| 124 | 124 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 (num_parameters - 1 - i) * kPointerSize; | 225 (num_parameters - 1 - i) * kPointerSize; |
| 226 // Load parameter from stack. | 226 // Load parameter from stack. |
| 227 __ mov(eax, Operand(ebp, parameter_offset)); | 227 __ mov(eax, Operand(ebp, parameter_offset)); |
| 228 // Store it in the context. | 228 // Store it in the context. |
| 229 int context_offset = Context::SlotOffset(var->index()); | 229 int context_offset = Context::SlotOffset(var->index()); |
| 230 __ mov(Operand(esi, context_offset), eax); | 230 __ mov(Operand(esi, context_offset), eax); |
| 231 // Update the write barrier. This clobbers eax and ebx. | 231 // Update the write barrier. This clobbers eax and ebx. |
| 232 __ RecordWriteContextSlot(esi, | 232 __ RecordWriteContextSlot(esi, |
| 233 context_offset, | 233 context_offset, |
| 234 eax, | 234 eax, |
| 235 ebx, | 235 ebx); |
| 236 kDontSaveFPRegs); | |
| 237 } | 236 } |
| 238 } | 237 } |
| 239 } | 238 } |
| 240 | 239 |
| 241 Variable* arguments = scope()->arguments(); | 240 Variable* arguments = scope()->arguments(); |
| 242 if (arguments != NULL) { | 241 if (arguments != NULL) { |
| 243 // Function uses arguments object. | 242 // Function uses arguments object. |
| 244 Comment cmnt(masm_, "[ Allocate arguments object"); | 243 Comment cmnt(masm_, "[ Allocate arguments object"); |
| 245 if (function_in_register) { | 244 if (function_in_register) { |
| 246 __ push(edi); | 245 __ push(edi); |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 | 440 |
| 442 void FullCodeGenerator::TestContext::Plug(Variable* var) const { | 441 void FullCodeGenerator::TestContext::Plug(Variable* var) const { |
| 443 // For simplicity we always test the accumulator register. | 442 // For simplicity we always test the accumulator register. |
| 444 codegen()->GetVar(result_register(), var); | 443 codegen()->GetVar(result_register(), var); |
| 445 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 444 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
| 446 codegen()->DoTest(this); | 445 codegen()->DoTest(this); |
| 447 } | 446 } |
| 448 | 447 |
| 449 | 448 |
| 450 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { | 449 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
| 451 UNREACHABLE(); // Not used on IA32. | 450 UNREACHABLE(); // Not used on X87. |
| 452 } | 451 } |
| 453 | 452 |
| 454 | 453 |
| 455 void FullCodeGenerator::AccumulatorValueContext::Plug( | 454 void FullCodeGenerator::AccumulatorValueContext::Plug( |
| 456 Heap::RootListIndex index) const { | 455 Heap::RootListIndex index) const { |
| 457 UNREACHABLE(); // Not used on IA32. | 456 UNREACHABLE(); // Not used on X87. |
| 458 } | 457 } |
| 459 | 458 |
| 460 | 459 |
| 461 void FullCodeGenerator::StackValueContext::Plug( | 460 void FullCodeGenerator::StackValueContext::Plug( |
| 462 Heap::RootListIndex index) const { | 461 Heap::RootListIndex index) const { |
| 463 UNREACHABLE(); // Not used on IA32. | 462 UNREACHABLE(); // Not used on X87. |
| 464 } | 463 } |
| 465 | 464 |
| 466 | 465 |
| 467 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { | 466 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { |
| 468 UNREACHABLE(); // Not used on IA32. | 467 UNREACHABLE(); // Not used on X87. |
| 469 } | 468 } |
| 470 | 469 |
| 471 | 470 |
| 472 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { | 471 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { |
| 473 } | 472 } |
| 474 | 473 |
| 475 | 474 |
| 476 void FullCodeGenerator::AccumulatorValueContext::Plug( | 475 void FullCodeGenerator::AccumulatorValueContext::Plug( |
| 477 Handle<Object> lit) const { | 476 Handle<Object> lit) const { |
| 478 if (lit->IsSmi()) { | 477 if (lit->IsSmi()) { |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 ASSERT(!scratch0.is(src)); | 697 ASSERT(!scratch0.is(src)); |
| 699 ASSERT(!scratch0.is(scratch1)); | 698 ASSERT(!scratch0.is(scratch1)); |
| 700 ASSERT(!scratch1.is(src)); | 699 ASSERT(!scratch1.is(src)); |
| 701 MemOperand location = VarOperand(var, scratch0); | 700 MemOperand location = VarOperand(var, scratch0); |
| 702 __ mov(location, src); | 701 __ mov(location, src); |
| 703 | 702 |
| 704 // Emit the write barrier code if the location is in the heap. | 703 // Emit the write barrier code if the location is in the heap. |
| 705 if (var->IsContextSlot()) { | 704 if (var->IsContextSlot()) { |
| 706 int offset = Context::SlotOffset(var->index()); | 705 int offset = Context::SlotOffset(var->index()); |
| 707 ASSERT(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi)); | 706 ASSERT(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi)); |
| 708 __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs); | 707 __ RecordWriteContextSlot(scratch0, offset, src, scratch1); |
| 709 } | 708 } |
| 710 } | 709 } |
| 711 | 710 |
| 712 | 711 |
| 713 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, | 712 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, |
| 714 bool should_normalize, | 713 bool should_normalize, |
| 715 Label* if_true, | 714 Label* if_true, |
| 716 Label* if_false) { | 715 Label* if_false) { |
| 717 // Only prepare for bailouts before splits if we're in a test | 716 // Only prepare for bailouts before splits if we're in a test |
| 718 // context. Otherwise, we let the Visit function deal with the | 717 // context. Otherwise, we let the Visit function deal with the |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 case Variable::CONTEXT: { | 831 case Variable::CONTEXT: { |
| 833 Comment cmnt(masm_, "[ FunctionDeclaration"); | 832 Comment cmnt(masm_, "[ FunctionDeclaration"); |
| 834 EmitDebugCheckDeclarationContext(variable); | 833 EmitDebugCheckDeclarationContext(variable); |
| 835 VisitForAccumulatorValue(declaration->fun()); | 834 VisitForAccumulatorValue(declaration->fun()); |
| 836 __ mov(ContextOperand(esi, variable->index()), result_register()); | 835 __ mov(ContextOperand(esi, variable->index()), result_register()); |
| 837 // We know that we have written a function, which is not a smi. | 836 // We know that we have written a function, which is not a smi. |
| 838 __ RecordWriteContextSlot(esi, | 837 __ RecordWriteContextSlot(esi, |
| 839 Context::SlotOffset(variable->index()), | 838 Context::SlotOffset(variable->index()), |
| 840 result_register(), | 839 result_register(), |
| 841 ecx, | 840 ecx, |
| 842 kDontSaveFPRegs, | |
| 843 EMIT_REMEMBERED_SET, | 841 EMIT_REMEMBERED_SET, |
| 844 OMIT_SMI_CHECK); | 842 OMIT_SMI_CHECK); |
| 845 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 843 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
| 846 break; | 844 break; |
| 847 } | 845 } |
| 848 | 846 |
| 849 case Variable::LOOKUP: { | 847 case Variable::LOOKUP: { |
| 850 Comment cmnt(masm_, "[ FunctionDeclaration"); | 848 Comment cmnt(masm_, "[ FunctionDeclaration"); |
| 851 __ push(esi); | 849 __ push(esi); |
| 852 __ push(Immediate(variable->name())); | 850 __ push(Immediate(variable->name())); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 872 __ mov(eax, ContextOperand(eax, variable->interface()->Index())); | 870 __ mov(eax, ContextOperand(eax, variable->interface()->Index())); |
| 873 __ mov(eax, ContextOperand(eax, Context::EXTENSION_INDEX)); | 871 __ mov(eax, ContextOperand(eax, Context::EXTENSION_INDEX)); |
| 874 | 872 |
| 875 // Assign it. | 873 // Assign it. |
| 876 __ mov(ContextOperand(esi, variable->index()), eax); | 874 __ mov(ContextOperand(esi, variable->index()), eax); |
| 877 // We know that we have written a module, which is not a smi. | 875 // We know that we have written a module, which is not a smi. |
| 878 __ RecordWriteContextSlot(esi, | 876 __ RecordWriteContextSlot(esi, |
| 879 Context::SlotOffset(variable->index()), | 877 Context::SlotOffset(variable->index()), |
| 880 eax, | 878 eax, |
| 881 ecx, | 879 ecx, |
| 882 kDontSaveFPRegs, | |
| 883 EMIT_REMEMBERED_SET, | 880 EMIT_REMEMBERED_SET, |
| 884 OMIT_SMI_CHECK); | 881 OMIT_SMI_CHECK); |
| 885 PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS); | 882 PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS); |
| 886 | 883 |
| 887 // Traverse into body. | 884 // Traverse into body. |
| 888 Visit(declaration->module()); | 885 Visit(declaration->module()); |
| 889 } | 886 } |
| 890 | 887 |
| 891 | 888 |
| 892 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) { | 889 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) { |
| (...skipping 872 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1765 if (IsFastObjectElementsKind(constant_elements_kind)) { | 1762 if (IsFastObjectElementsKind(constant_elements_kind)) { |
| 1766 // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they | 1763 // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they |
| 1767 // cannot transition and don't need to call the runtime stub. | 1764 // cannot transition and don't need to call the runtime stub. |
| 1768 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 1765 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
| 1769 __ mov(ebx, Operand(esp, kPointerSize)); // Copy of array literal. | 1766 __ mov(ebx, Operand(esp, kPointerSize)); // Copy of array literal. |
| 1770 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); | 1767 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); |
| 1771 // Store the subexpression value in the array's elements. | 1768 // Store the subexpression value in the array's elements. |
| 1772 __ mov(FieldOperand(ebx, offset), result_register()); | 1769 __ mov(FieldOperand(ebx, offset), result_register()); |
| 1773 // Update the write barrier for the array store. | 1770 // Update the write barrier for the array store. |
| 1774 __ RecordWriteField(ebx, offset, result_register(), ecx, | 1771 __ RecordWriteField(ebx, offset, result_register(), ecx, |
| 1775 kDontSaveFPRegs, | |
| 1776 EMIT_REMEMBERED_SET, | 1772 EMIT_REMEMBERED_SET, |
| 1777 INLINE_SMI_CHECK); | 1773 INLINE_SMI_CHECK); |
| 1778 } else { | 1774 } else { |
| 1779 // Store the subexpression value in the array's elements. | 1775 // Store the subexpression value in the array's elements. |
| 1780 __ mov(ecx, Immediate(Smi::FromInt(i))); | 1776 __ mov(ecx, Immediate(Smi::FromInt(i))); |
| 1781 StoreArrayLiteralElementStub stub(isolate()); | 1777 StoreArrayLiteralElementStub stub(isolate()); |
| 1782 __ CallStub(&stub); | 1778 __ CallStub(&stub); |
| 1783 } | 1779 } |
| 1784 | 1780 |
| 1785 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); | 1781 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1924 __ bind(&continuation); | 1920 __ bind(&continuation); |
| 1925 __ jmp(&resume); | 1921 __ jmp(&resume); |
| 1926 | 1922 |
| 1927 __ bind(&suspend); | 1923 __ bind(&suspend); |
| 1928 VisitForAccumulatorValue(expr->generator_object()); | 1924 VisitForAccumulatorValue(expr->generator_object()); |
| 1929 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); | 1925 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |
| 1930 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), | 1926 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), |
| 1931 Immediate(Smi::FromInt(continuation.pos()))); | 1927 Immediate(Smi::FromInt(continuation.pos()))); |
| 1932 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); | 1928 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); |
| 1933 __ mov(ecx, esi); | 1929 __ mov(ecx, esi); |
| 1934 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, | 1930 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); |
| 1935 kDontSaveFPRegs); | |
| 1936 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); | 1931 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); |
| 1937 __ cmp(esp, ebx); | 1932 __ cmp(esp, ebx); |
| 1938 __ j(equal, &post_runtime); | 1933 __ j(equal, &post_runtime); |
| 1939 __ push(eax); // generator object | 1934 __ push(eax); // generator object |
| 1940 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); | 1935 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); |
| 1941 __ mov(context_register(), | 1936 __ mov(context_register(), |
| 1942 Operand(ebp, StandardFrameConstants::kContextOffset)); | 1937 Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 1943 __ bind(&post_runtime); | 1938 __ bind(&post_runtime); |
| 1944 __ pop(result_register()); | 1939 __ pop(result_register()); |
| 1945 EmitReturnSequence(); | 1940 EmitReturnSequence(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1996 __ jmp(&l_resume); | 1991 __ jmp(&l_resume); |
| 1997 __ bind(&l_suspend); | 1992 __ bind(&l_suspend); |
| 1998 const int generator_object_depth = kPointerSize + handler_size; | 1993 const int generator_object_depth = kPointerSize + handler_size; |
| 1999 __ mov(eax, Operand(esp, generator_object_depth)); | 1994 __ mov(eax, Operand(esp, generator_object_depth)); |
| 2000 __ push(eax); // g | 1995 __ push(eax); // g |
| 2001 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); | 1996 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); |
| 2002 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), | 1997 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), |
| 2003 Immediate(Smi::FromInt(l_continuation.pos()))); | 1998 Immediate(Smi::FromInt(l_continuation.pos()))); |
| 2004 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); | 1999 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); |
| 2005 __ mov(ecx, esi); | 2000 __ mov(ecx, esi); |
| 2006 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, | 2001 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); |
| 2007 kDontSaveFPRegs); | |
| 2008 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); | 2002 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); |
| 2009 __ mov(context_register(), | 2003 __ mov(context_register(), |
| 2010 Operand(ebp, StandardFrameConstants::kContextOffset)); | 2004 Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2011 __ pop(eax); // result | 2005 __ pop(eax); // result |
| 2012 EmitReturnSequence(); | 2006 EmitReturnSequence(); |
| 2013 __ bind(&l_resume); // received in eax | 2007 __ bind(&l_resume); // received in eax |
| 2014 __ PopTryHandler(); | 2008 __ PopTryHandler(); |
| 2015 | 2009 |
| 2016 // receiver = iter; f = iter.next; arg = received; | 2010 // receiver = iter; f = iter.next; arg = received; |
| 2017 __ bind(&l_next); | 2011 __ bind(&l_next); |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2191 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 2185 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
| 2192 isolate()->factory()->empty_fixed_array()); | 2186 isolate()->factory()->empty_fixed_array()); |
| 2193 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 2187 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
| 2194 isolate()->factory()->empty_fixed_array()); | 2188 isolate()->factory()->empty_fixed_array()); |
| 2195 __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx); | 2189 __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx); |
| 2196 __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx); | 2190 __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx); |
| 2197 | 2191 |
| 2198 // Only the value field needs a write barrier, as the other values are in the | 2192 // Only the value field needs a write barrier, as the other values are in the |
| 2199 // root set. | 2193 // root set. |
| 2200 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, | 2194 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, |
| 2201 ecx, edx, kDontSaveFPRegs); | 2195 ecx, edx); |
| 2202 } | 2196 } |
| 2203 | 2197 |
| 2204 | 2198 |
| 2205 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 2199 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 2206 SetSourcePosition(prop->position()); | 2200 SetSourcePosition(prop->position()); |
| 2207 Literal* key = prop->key()->AsLiteral(); | 2201 Literal* key = prop->key()->AsLiteral(); |
| 2208 ASSERT(!key->value()->IsSmi()); | 2202 ASSERT(!key->value()->IsSmi()); |
| 2209 __ mov(ecx, Immediate(key->value())); | 2203 __ mov(ecx, Immediate(key->value())); |
| 2210 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); | 2204 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 2211 } | 2205 } |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2372 context()->Plug(eax); | 2366 context()->Plug(eax); |
| 2373 } | 2367 } |
| 2374 | 2368 |
| 2375 | 2369 |
| 2376 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( | 2370 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( |
| 2377 Variable* var, MemOperand location) { | 2371 Variable* var, MemOperand location) { |
| 2378 __ mov(location, eax); | 2372 __ mov(location, eax); |
| 2379 if (var->IsContextSlot()) { | 2373 if (var->IsContextSlot()) { |
| 2380 __ mov(edx, eax); | 2374 __ mov(edx, eax); |
| 2381 int offset = Context::SlotOffset(var->index()); | 2375 int offset = Context::SlotOffset(var->index()); |
| 2382 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); | 2376 __ RecordWriteContextSlot(ecx, offset, edx, ebx); |
| 2383 } | 2377 } |
| 2384 } | 2378 } |
| 2385 | 2379 |
| 2386 | 2380 |
| 2387 void FullCodeGenerator::EmitCallStoreContextSlot( | 2381 void FullCodeGenerator::EmitCallStoreContextSlot( |
| 2388 Handle<String> name, StrictMode strict_mode) { | 2382 Handle<String> name, StrictMode strict_mode) { |
| 2389 __ push(eax); // Value. | 2383 __ push(eax); // Value. |
| 2390 __ push(esi); // Context. | 2384 __ push(esi); // Context. |
| 2391 __ push(Immediate(name)); | 2385 __ push(Immediate(name)); |
| 2392 __ push(Immediate(Smi::FromInt(strict_mode))); | 2386 __ push(Immediate(Smi::FromInt(strict_mode))); |
| (...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3408 } | 3402 } |
| 3409 | 3403 |
| 3410 | 3404 |
| 3411 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { | 3405 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { |
| 3412 // Load the arguments on the stack and call the runtime function. | 3406 // Load the arguments on the stack and call the runtime function. |
| 3413 ZoneList<Expression*>* args = expr->arguments(); | 3407 ZoneList<Expression*>* args = expr->arguments(); |
| 3414 ASSERT(args->length() == 2); | 3408 ASSERT(args->length() == 2); |
| 3415 VisitForStackValue(args->at(0)); | 3409 VisitForStackValue(args->at(0)); |
| 3416 VisitForStackValue(args->at(1)); | 3410 VisitForStackValue(args->at(1)); |
| 3417 | 3411 |
| 3418 MathPowStub stub(isolate(), MathPowStub::ON_STACK); | 3412 __ CallRuntime(Runtime::kHiddenMathPowSlow, 2); |
| 3419 __ CallStub(&stub); | |
| 3420 context()->Plug(eax); | 3413 context()->Plug(eax); |
| 3421 } | 3414 } |
| 3422 | 3415 |
| 3423 | 3416 |
| 3424 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { | 3417 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { |
| 3425 ZoneList<Expression*>* args = expr->arguments(); | 3418 ZoneList<Expression*>* args = expr->arguments(); |
| 3426 ASSERT(args->length() == 2); | 3419 ASSERT(args->length() == 2); |
| 3427 | 3420 |
| 3428 VisitForStackValue(args->at(0)); // Load the object. | 3421 VisitForStackValue(args->at(0)); // Load the object. |
| 3429 VisitForAccumulatorValue(args->at(1)); // Load the value. | 3422 VisitForAccumulatorValue(args->at(1)); // Load the value. |
| 3430 __ pop(ebx); // eax = value. ebx = object. | 3423 __ pop(ebx); // eax = value. ebx = object. |
| 3431 | 3424 |
| 3432 Label done; | 3425 Label done; |
| 3433 // If the object is a smi, return the value. | 3426 // If the object is a smi, return the value. |
| 3434 __ JumpIfSmi(ebx, &done, Label::kNear); | 3427 __ JumpIfSmi(ebx, &done, Label::kNear); |
| 3435 | 3428 |
| 3436 // If the object is not a value type, return the value. | 3429 // If the object is not a value type, return the value. |
| 3437 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); | 3430 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); |
| 3438 __ j(not_equal, &done, Label::kNear); | 3431 __ j(not_equal, &done, Label::kNear); |
| 3439 | 3432 |
| 3440 // Store the value. | 3433 // Store the value. |
| 3441 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); | 3434 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); |
| 3442 | 3435 |
| 3443 // Update the write barrier. Save the value as it will be | 3436 // Update the write barrier. Save the value as it will be |
| 3444 // overwritten by the write barrier code and is needed afterward. | 3437 // overwritten by the write barrier code and is needed afterward. |
| 3445 __ mov(edx, eax); | 3438 __ mov(edx, eax); |
| 3446 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs); | 3439 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx); |
| 3447 | 3440 |
| 3448 __ bind(&done); | 3441 __ bind(&done); |
| 3449 context()->Plug(eax); | 3442 context()->Plug(eax); |
| 3450 } | 3443 } |
| 3451 | 3444 |
| 3452 | 3445 |
| 3453 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { | 3446 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { |
| 3454 ZoneList<Expression*>* args = expr->arguments(); | 3447 ZoneList<Expression*>* args = expr->arguments(); |
| 3455 ASSERT_EQ(args->length(), 1); | 3448 ASSERT_EQ(args->length(), 1); |
| 3456 | 3449 |
| (...skipping 1335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4792 | 4785 |
| 4793 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4786 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
| 4794 Assembler::target_address_at(call_target_address, | 4787 Assembler::target_address_at(call_target_address, |
| 4795 unoptimized_code)); | 4788 unoptimized_code)); |
| 4796 return OSR_AFTER_STACK_CHECK; | 4789 return OSR_AFTER_STACK_CHECK; |
| 4797 } | 4790 } |
| 4798 | 4791 |
| 4799 | 4792 |
| 4800 } } // namespace v8::internal | 4793 } } // namespace v8::internal |
| 4801 | 4794 |
| 4802 #endif // V8_TARGET_ARCH_IA32 | 4795 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |