| Index: src/x64/stub-cache-x64.cc
|
| ===================================================================
|
| --- src/x64/stub-cache-x64.cc (revision 8618)
|
| +++ src/x64/stub-cache-x64.cc (working copy)
|
| @@ -105,7 +105,7 @@
|
| __ j(not_zero, miss_label);
|
|
|
| // Check that receiver is a JSObject.
|
| - __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE);
|
| + __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE);
|
| __ j(below, miss_label);
|
|
|
| // Load properties array.
|
| @@ -478,10 +478,12 @@
|
| public:
|
| CallInterceptorCompiler(StubCompiler* stub_compiler,
|
| const ParameterCount& arguments,
|
| - Register name)
|
| + Register name,
|
| + Code::ExtraICState extra_ic_state)
|
| : stub_compiler_(stub_compiler),
|
| arguments_(arguments),
|
| - name_(name) {}
|
| + name_(name),
|
| + extra_ic_state_(extra_ic_state) {}
|
|
|
| MaybeObject* Compile(MacroAssembler* masm,
|
| JSObject* object,
|
| @@ -606,8 +608,11 @@
|
| arguments_.immediate());
|
| if (result->IsFailure()) return result;
|
| } else {
|
| + CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
| + ? CALL_AS_FUNCTION
|
| + : CALL_AS_METHOD;
|
| __ InvokeFunction(optimization.constant_function(), arguments_,
|
| - JUMP_FUNCTION);
|
| + JUMP_FUNCTION, NullCallWrapper(), call_kind);
|
| }
|
|
|
| // Deferred code for fast API call case---clean preallocated space.
|
| @@ -686,6 +691,7 @@
|
| StubCompiler* stub_compiler_;
|
| const ParameterCount& arguments_;
|
| Register name_;
|
| + Code::ExtraICState extra_ic_state_;
|
| };
|
|
|
|
|
| @@ -1350,7 +1356,11 @@
|
| }
|
|
|
| // Invoke the function.
|
| - __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION);
|
| + CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
| + ? CALL_AS_FUNCTION
|
| + : CALL_AS_METHOD;
|
| + __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
|
| + NullCallWrapper(), call_kind);
|
|
|
| // Handle call cache miss.
|
| __ bind(&miss);
|
| @@ -1837,7 +1847,11 @@
|
| // Tail call the full function. We do not have to patch the receiver
|
| // because the function makes no use of it.
|
| __ bind(&slow);
|
| - __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
|
| + CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
| + ? CALL_AS_FUNCTION
|
| + : CALL_AS_METHOD;
|
| + __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
|
| + NullCallWrapper(), call_kind);
|
|
|
| __ bind(&miss);
|
| // rcx: function name.
|
| @@ -1950,7 +1964,11 @@
|
| // Tail call the full function. We do not have to patch the receiver
|
| // because the function makes no use of it.
|
| __ bind(&slow);
|
| - __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
|
| + CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
| + ? CALL_AS_FUNCTION
|
| + : CALL_AS_METHOD;
|
| + __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
|
| + NullCallWrapper(), call_kind);
|
|
|
| __ bind(&miss);
|
| // rcx: function name.
|
| @@ -2144,7 +2162,11 @@
|
| UNREACHABLE();
|
| }
|
|
|
| - __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
|
| + CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
| + ? CALL_AS_FUNCTION
|
| + : CALL_AS_METHOD;
|
| + __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
|
| + NullCallWrapper(), call_kind);
|
|
|
| // Handle call cache miss.
|
| __ bind(&miss);
|
| @@ -2181,7 +2203,7 @@
|
| // Get the receiver from the stack.
|
| __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
|
|
|
| - CallInterceptorCompiler compiler(this, arguments(), rcx);
|
| + CallInterceptorCompiler compiler(this, arguments(), rcx, extra_ic_state_);
|
| MaybeObject* result = compiler.Compile(masm(),
|
| object,
|
| holder,
|
| @@ -2211,7 +2233,11 @@
|
|
|
| // Invoke the function.
|
| __ movq(rdi, rax);
|
| - __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION);
|
| + CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
| + ? CALL_AS_FUNCTION
|
| + : CALL_AS_METHOD;
|
| + __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
|
| + NullCallWrapper(), call_kind);
|
|
|
| // Handle load cache miss.
|
| __ bind(&miss);
|
| @@ -2223,13 +2249,11 @@
|
| }
|
|
|
|
|
| -MaybeObject* CallStubCompiler::CompileCallGlobal(
|
| - JSObject* object,
|
| - GlobalObject* holder,
|
| - JSGlobalPropertyCell* cell,
|
| - JSFunction* function,
|
| - String* name,
|
| - Code::ExtraICState extra_ic_state) {
|
| +MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
|
| + GlobalObject* holder,
|
| + JSGlobalPropertyCell* cell,
|
| + JSFunction* function,
|
| + String* name) {
|
| // ----------- S t a t e -------------
|
| // rcx : function name
|
| // rsp[0] : return address
|
| @@ -2274,7 +2298,7 @@
|
| __ IncrementCounter(counters->call_global_inline(), 1);
|
| ASSERT(function->is_compiled());
|
| ParameterCount expected(function->shared()->formal_parameter_count());
|
| - CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
|
| + CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
| ? CALL_AS_FUNCTION
|
| : CALL_AS_METHOD;
|
| if (V8::UseCrankshaft()) {
|
| @@ -2529,18 +2553,18 @@
|
| }
|
|
|
|
|
| -MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
|
| - Map* receiver_map) {
|
| +MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) {
|
| // ----------- S t a t e -------------
|
| // -- rax : value
|
| // -- rcx : key
|
| // -- rdx : receiver
|
| // -- rsp[0] : return address
|
| // -----------------------------------
|
| + Code* stub;
|
| + JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
|
| bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
|
| MaybeObject* maybe_stub =
|
| - KeyedStoreFastElementStub(is_js_array).TryGetCode();
|
| - Code* stub;
|
| + KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode();
|
| if (!maybe_stub->To(&stub)) return maybe_stub;
|
| __ DispatchMap(rdx,
|
| Handle<Map>(receiver_map),
|
| @@ -2989,14 +3013,15 @@
|
| }
|
|
|
|
|
| -MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
|
| +MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) {
|
| // ----------- S t a t e -------------
|
| // -- rax : key
|
| // -- rdx : receiver
|
| // -- rsp[0] : return address
|
| // -----------------------------------
|
| - MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
|
| Code* stub;
|
| + JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
|
| + MaybeObject* maybe_stub = KeyedLoadElementStub(elements_kind).TryGetCode();
|
| if (!maybe_stub->To(&stub)) return maybe_stub;
|
| __ DispatchMap(rdx,
|
| Handle<Map>(receiver_map),
|
| @@ -3175,60 +3200,58 @@
|
| }
|
|
|
|
|
| -MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
|
| - JSObject*receiver, ExternalArrayType array_type) {
|
| +#undef __
|
| +#define __ ACCESS_MASM(masm)
|
| +
|
| +
|
| +void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
| + MacroAssembler* masm) {
|
| // ----------- S t a t e -------------
|
| // -- rax : key
|
| // -- rdx : receiver
|
| // -- rsp[0] : return address
|
| // -----------------------------------
|
| - MaybeObject* maybe_stub =
|
| - KeyedLoadExternalArrayStub(array_type).TryGetCode();
|
| - Code* stub;
|
| - if (!maybe_stub->To(&stub)) return maybe_stub;
|
| - __ DispatchMap(rdx,
|
| - Handle<Map>(receiver->map()),
|
| - Handle<Code>(stub),
|
| - DO_SMI_CHECK);
|
| + Label slow, miss_force_generic;
|
|
|
| - Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
|
| - __ jmp(ic, RelocInfo::CODE_TARGET);
|
| + // This stub is meant to be tail-jumped to, the receiver must already
|
| + // have been verified by the caller to not be a smi.
|
|
|
| - // Return the generated code.
|
| - return GetCode();
|
| -}
|
| + __ JumpIfNotSmi(rax, &miss_force_generic);
|
| + __ SmiToInteger32(rbx, rax);
|
| + __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
|
|
|
| -MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
|
| - JSObject* receiver, ExternalArrayType array_type) {
|
| + // Check whether the elements is a number dictionary.
|
| + // rdx: receiver
|
| + // rax: key
|
| + // rbx: key as untagged int32
|
| + // rcx: elements
|
| + __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax);
|
| + __ ret(0);
|
| +
|
| + __ bind(&slow);
|
| // ----------- S t a t e -------------
|
| - // -- rax : value
|
| - // -- rcx : key
|
| + // -- rax : key
|
| // -- rdx : receiver
|
| - // -- rsp[0] : return address
|
| + // -- rsp[0] : return address
|
| // -----------------------------------
|
| - MaybeObject* maybe_stub =
|
| - KeyedStoreExternalArrayStub(array_type).TryGetCode();
|
| - Code* stub;
|
| - if (!maybe_stub->To(&stub)) return maybe_stub;
|
| - __ DispatchMap(rdx,
|
| - Handle<Map>(receiver->map()),
|
| - Handle<Code>(stub),
|
| - DO_SMI_CHECK);
|
| + Handle<Code> slow_ic =
|
| + masm->isolate()->builtins()->KeyedLoadIC_Slow();
|
| + __ jmp(slow_ic, RelocInfo::CODE_TARGET);
|
|
|
| - Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
| - __ jmp(ic, RelocInfo::CODE_TARGET);
|
| -
|
| - return GetCode();
|
| + __ bind(&miss_force_generic);
|
| + // ----------- S t a t e -------------
|
| + // -- rax : key
|
| + // -- rdx : receiver
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| + Handle<Code> miss_ic =
|
| + masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
|
| + __ jmp(miss_ic, RelocInfo::CODE_TARGET);
|
| }
|
|
|
| -
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm)
|
| -
|
| -
|
| void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
| MacroAssembler* masm,
|
| - ExternalArrayType array_type) {
|
| + JSObject::ElementsKind elements_kind) {
|
| // ----------- S t a t e -------------
|
| // -- rax : key
|
| // -- rdx : receiver
|
| @@ -3255,30 +3278,30 @@
|
| // rbx: elements array
|
| __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
|
| // rbx: base pointer of external storage
|
| - switch (array_type) {
|
| - case kExternalByteArray:
|
| + switch (elements_kind) {
|
| + case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
| __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
|
| break;
|
| - case kExternalPixelArray:
|
| - case kExternalUnsignedByteArray:
|
| + case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
| + case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0));
|
| break;
|
| - case kExternalShortArray:
|
| + case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
| __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0));
|
| break;
|
| - case kExternalUnsignedShortArray:
|
| + case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0));
|
| break;
|
| - case kExternalIntArray:
|
| + case JSObject::EXTERNAL_INT_ELEMENTS:
|
| __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0));
|
| break;
|
| - case kExternalUnsignedIntArray:
|
| + case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| __ movl(rcx, Operand(rbx, rcx, times_4, 0));
|
| break;
|
| - case kExternalFloatArray:
|
| + case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
| __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0));
|
| break;
|
| - case kExternalDoubleArray:
|
| + case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
| __ movsd(xmm0, Operand(rbx, rcx, times_8, 0));
|
| break;
|
| default:
|
| @@ -3294,7 +3317,7 @@
|
| // xmm0: value as double.
|
|
|
| ASSERT(kSmiValueSize == 32);
|
| - if (array_type == kExternalUnsignedIntArray) {
|
| + if (elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) {
|
| // For the UnsignedInt array type, we need to see whether
|
| // the value can be represented in a Smi. If not, we need to convert
|
| // it to a HeapNumber.
|
| @@ -3318,8 +3341,8 @@
|
| __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
|
| __ movq(rax, rcx);
|
| __ ret(0);
|
| - } else if (array_type == kExternalFloatArray ||
|
| - array_type == kExternalDoubleArray) {
|
| + } else if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS ||
|
| + elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
| // For the floating-point array type, we need to always allocate a
|
| // HeapNumber.
|
| __ AllocateHeapNumber(rcx, rbx, &slow);
|
| @@ -3362,7 +3385,7 @@
|
|
|
| void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
| MacroAssembler* masm,
|
| - ExternalArrayType array_type) {
|
| + JSObject::ElementsKind elements_kind) {
|
| // ----------- S t a t e -------------
|
| // -- rax : value
|
| // -- rcx : key
|
| @@ -3392,7 +3415,7 @@
|
| // rbx: elements array
|
| // rdi: untagged key
|
| Label check_heap_number;
|
| - if (array_type == kExternalPixelArray) {
|
| + if (elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS) {
|
| // Float to pixel conversion is only implemented in the runtime for now.
|
| __ JumpIfNotSmi(rax, &slow);
|
| } else {
|
| @@ -3402,8 +3425,8 @@
|
| __ SmiToInteger32(rdx, rax);
|
| __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
|
| // rbx: base pointer of external storage
|
| - switch (array_type) {
|
| - case kExternalPixelArray:
|
| + switch (elements_kind) {
|
| + case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
| { // Clamp the value to [0..255].
|
| Label done;
|
| __ testl(rdx, Immediate(0xFFFFFF00));
|
| @@ -3414,36 +3437,39 @@
|
| }
|
| __ movb(Operand(rbx, rdi, times_1, 0), rdx);
|
| break;
|
| - case kExternalByteArray:
|
| - case kExternalUnsignedByteArray:
|
| + case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
| + case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| __ movb(Operand(rbx, rdi, times_1, 0), rdx);
|
| break;
|
| - case kExternalShortArray:
|
| - case kExternalUnsignedShortArray:
|
| + case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
| + case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| __ movw(Operand(rbx, rdi, times_2, 0), rdx);
|
| break;
|
| - case kExternalIntArray:
|
| - case kExternalUnsignedIntArray:
|
| + case JSObject::EXTERNAL_INT_ELEMENTS:
|
| + case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| __ movl(Operand(rbx, rdi, times_4, 0), rdx);
|
| break;
|
| - case kExternalFloatArray:
|
| + case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
| // Need to perform int-to-float conversion.
|
| __ cvtlsi2ss(xmm0, rdx);
|
| __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
|
| break;
|
| - case kExternalDoubleArray:
|
| + case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
| // Need to perform int-to-float conversion.
|
| __ cvtlsi2sd(xmm0, rdx);
|
| __ movsd(Operand(rbx, rdi, times_8, 0), xmm0);
|
| break;
|
| - default:
|
| + case JSObject::FAST_ELEMENTS:
|
| + case JSObject::FAST_DOUBLE_ELEMENTS:
|
| + case JSObject::DICTIONARY_ELEMENTS:
|
| + case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
|
| UNREACHABLE();
|
| break;
|
| }
|
| __ ret(0);
|
|
|
| // TODO(danno): handle heap number -> pixel array conversion
|
| - if (array_type != kExternalPixelArray) {
|
| + if (elements_kind != JSObject::EXTERNAL_PIXEL_ELEMENTS) {
|
| __ bind(&check_heap_number);
|
| // rax: value
|
| // rcx: key (a smi)
|
| @@ -3462,11 +3488,11 @@
|
| // rdi: untagged index
|
| // rbx: base pointer of external storage
|
| // top of FPU stack: value
|
| - if (array_type == kExternalFloatArray) {
|
| + if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
|
| __ cvtsd2ss(xmm0, xmm0);
|
| __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
|
| __ ret(0);
|
| - } else if (array_type == kExternalDoubleArray) {
|
| + } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
|
| __ movsd(Operand(rbx, rdi, times_8, 0), xmm0);
|
| __ ret(0);
|
| } else {
|
| @@ -3479,26 +3505,31 @@
|
| // rdx: value (converted to an untagged integer)
|
| // rdi: untagged index
|
| // rbx: base pointer of external storage
|
| - switch (array_type) {
|
| - case kExternalByteArray:
|
| - case kExternalUnsignedByteArray:
|
| + switch (elements_kind) {
|
| + case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
| + case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| __ cvttsd2si(rdx, xmm0);
|
| __ movb(Operand(rbx, rdi, times_1, 0), rdx);
|
| break;
|
| - case kExternalShortArray:
|
| - case kExternalUnsignedShortArray:
|
| + case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
| + case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| __ cvttsd2si(rdx, xmm0);
|
| __ movw(Operand(rbx, rdi, times_2, 0), rdx);
|
| break;
|
| - case kExternalIntArray:
|
| - case kExternalUnsignedIntArray: {
|
| + case JSObject::EXTERNAL_INT_ELEMENTS:
|
| + case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| // Convert to int64, so that NaN and infinities become
|
| // 0x8000000000000000, which is zero mod 2^32.
|
| __ cvttsd2siq(rdx, xmm0);
|
| __ movl(Operand(rbx, rdi, times_4, 0), rdx);
|
| break;
|
| - }
|
| - default:
|
| + case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
| + case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
| + case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
| + case JSObject::FAST_ELEMENTS:
|
| + case JSObject::FAST_DOUBLE_ELEMENTS:
|
| + case JSObject::DICTIONARY_ELEMENTS:
|
| + case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
|
| UNREACHABLE();
|
| break;
|
| }
|
|
|