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 |