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 |