Chromium Code Reviews| Index: src/ia32/code-stubs-ia32.cc |
| diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc |
| index 27957d0f50844503682a3d4f8e75fe328846c184..1f08559b16cea10decbf6010dc50379d48118875 100644 |
| --- a/src/ia32/code-stubs-ia32.cc |
| +++ b/src/ia32/code-stubs-ia32.cc |
| @@ -37,6 +37,7 @@ |
| #include "runtime.h" |
| #include "stub-cache.h" |
| #include "codegen.h" |
| +#include "runtime.h" |
| namespace v8 { |
| namespace internal { |
| @@ -47,8 +48,8 @@ void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( |
| CodeStubInterfaceDescriptor* descriptor) { |
| static Register registers[] = { edx, ecx }; |
| descriptor->register_param_count_ = 2; |
| - descriptor->register_params_ = registers; |
| descriptor->stack_parameter_count_ = NULL; |
|
Toon Verwaest
2013/02/13 15:14:51
Unnecessary move.
|
| + descriptor->register_params_ = registers; |
| descriptor->deoptimization_handler_ = |
| FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); |
| } |
| @@ -65,6 +66,40 @@ void TransitionElementsKindStub::InitializeInterfaceDescriptor( |
| } |
| +static void InitializeArrayConstructorDescriptor(Isolate* isolate, |
| + CodeStubInterfaceDescriptor* descriptor) { |
| + static Register registers[] = { edi, ebx }; |
| + descriptor->register_param_count_ = 2; |
| + // stack param count needs (constructor pointer, and single argument) |
| + descriptor->stack_parameter_count_ = &eax; |
| + descriptor->register_params_ = registers; |
| + descriptor->extra_expression_stack_count_ = 1; |
| + descriptor->deoptimization_handler_ = |
| + FUNCTION_ADDR(ArrayConstructor_StubFailure); |
| +} |
| + |
| + |
| +void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
| + Isolate* isolate, |
| + CodeStubInterfaceDescriptor* descriptor) { |
| + InitializeArrayConstructorDescriptor(isolate, descriptor); |
| +} |
| + |
| + |
| +void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( |
| + Isolate* isolate, |
| + CodeStubInterfaceDescriptor* descriptor) { |
| + InitializeArrayConstructorDescriptor(isolate, descriptor); |
| +} |
| + |
| + |
| +void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
| + Isolate* isolate, |
| + CodeStubInterfaceDescriptor* descriptor) { |
| + InitializeArrayConstructorDescriptor(isolate, descriptor); |
| +} |
| + |
| + |
| #define __ ACCESS_MASM(masm) |
| void ToNumberStub::Generate(MacroAssembler* masm) { |
| @@ -4810,7 +4845,7 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) { |
| // ebx : cache cell for call target |
| // edi : the function to call |
| Isolate* isolate = masm->isolate(); |
| - Label initialize, done; |
| + Label initialize, done, miss, megamorphic, not_array_function; |
| // Load the cache state into ecx. |
| __ mov(ecx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
| @@ -4818,22 +4853,64 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) { |
| // A monomorphic cache hit or an already megamorphic state: invoke the |
| // function without changing the state. |
| __ cmp(ecx, edi); |
| - __ j(equal, &done, Label::kNear); |
| + __ j(equal, &done, Label::kFar); |
|
Toon Verwaest
2013/02/13 15:14:51
I believe Label::kFar is the default, you can omit
mvstanton
2013/02/19 11:04:08
Done.
|
| __ cmp(ecx, Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); |
| - __ j(equal, &done, Label::kNear); |
| + __ j(equal, &done, Label::kFar); |
| + |
| + // Special handling of the Array() function, which caches not only the |
| + // monomorphic Array function but the initial ElementsKind with special |
| + // sentinels |
| + Handle<Object> terminal_kind_sentinel = |
| + TypeFeedbackCells::MonomorphicArraySentinel(LAST_FAST_ELEMENTS_KIND); |
| + __ cmp(ecx, Immediate(terminal_kind_sentinel)); |
| + __ j(above, &miss, Label::kFar); |
|
Toon Verwaest
2013/02/13 15:14:51
If you move this below the cmp, you can probably m
mvstanton
2013/02/19 11:04:08
I looked more carefully and it didn't seem possibl
|
| + // Load the global or builtins object from the current context |
| + __ mov(ecx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| + __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset)); |
| + // Make sure the function is the Array() function |
| + __ cmp(edi, Operand(ecx, |
| + Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
| + Label megamorphic_pre; |
| + __ j(not_equal, &megamorphic_pre, Label::kFar); |
|
Toon Verwaest
2013/02/13 15:14:51
Jump to megamorphic directly.
mvstanton
2013/02/19 11:04:08
Done.
|
| + __ jmp(&done); |
| + |
| + __ bind(&megamorphic_pre); |
| + __ jmp(&megamorphic, Label::kFar); |
| + |
| + __ bind(&miss); |
| // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
| // megamorphic. |
| __ cmp(ecx, Immediate(TypeFeedbackCells::UninitializedSentinel(isolate))); |
| - __ j(equal, &initialize, Label::kNear); |
| + __ j(equal, &initialize, Label::kFar); |
| // MegamorphicSentinel is an immortal immovable object (undefined) so no |
| // write-barrier is needed. |
| + __ bind(&megamorphic); |
| __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), |
| Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); |
| __ jmp(&done, Label::kNear); |
| - // An uninitialized cache is patched with the function. |
| + // An uninitialized cache is patched with the function or sentinel to |
| + // indicate the ElementsKind if function is the Array constructor. |
| __ bind(&initialize); |
| + __ mov(ecx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| + __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset)); |
|
Toon Verwaest
2013/02/13 15:14:51
Check if this can be folded together with the code
mvstanton
2013/02/19 11:04:08
Not foldable, but I have a new macro method: LoadG
|
| + // Make sure the function is the Array() function |
| + __ cmp(edi, Operand(ecx, |
| + Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
| + __ j(not_equal, ¬_array_function); |
| + |
| + // The target function is the Array constructor, install a sentinel value in |
| + // the constructor's type info cell that will track the initial ElementsKind |
| + // that should be used for the array when its constructed. |
| + Handle<Object> initial_kind_sentinel = |
| + TypeFeedbackCells::MonomorphicArraySentinel( |
| + GetInitialFastElementsKind()); |
| + __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), |
| + Immediate(initial_kind_sentinel)); |
| + __ jmp(&done); |
| + |
| + __ bind(¬_array_function); |
| __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), edi); |
| // No need for a write barrier here - cells are rescanned. |
| @@ -4949,10 +5026,10 @@ void CallConstructStub::Generate(MacroAssembler* masm) { |
| } |
| // Jump to the function-specific construct stub. |
| - __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| - __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kConstructStubOffset)); |
| - __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize)); |
| - __ jmp(ebx); |
| + __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| + __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); |
| + __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
| + __ jmp(ecx); |
| // edi: called object |
| // eax: number of arguments |