| Index: src/x64/stub-cache-x64.cc
|
| diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
|
| index ef6f7583882016c5133b4706b3cf4047aab6bf79..9df9b4300a1b17438417aa8abe150e4ce6502815 100644
|
| --- a/src/x64/stub-cache-x64.cc
|
| +++ b/src/x64/stub-cache-x64.cc
|
| @@ -747,6 +747,14 @@ void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
|
| }
|
|
|
|
|
| +void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
|
| + Code* code = masm->isolate()->builtins()->builtin(
|
| + Builtins::kKeyedLoadIC_MissForceGeneric);
|
| + Handle<Code> ic(code);
|
| + __ Jump(ic, RelocInfo::CODE_TARGET);
|
| +}
|
| +
|
| +
|
| // Both name_reg and receiver_reg are preserved on jumps to miss_label,
|
| // but may be destroyed if store is successful.
|
| void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
| @@ -2523,40 +2531,33 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
|
| }
|
|
|
|
|
| -MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized(
|
| - JSObject* receiver) {
|
| +MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized(Handle<Map> receiver_map) {
|
| // ----------- S t a t e -------------
|
| // -- rax : value
|
| // -- rcx : key
|
| // -- rdx : receiver
|
| // -- rsp[0] : return address
|
| // -----------------------------------
|
| - Label miss;
|
| + Label miss, miss_force_generic;
|
|
|
| - // Check that the receiver isn't a smi.
|
| - __ JumpIfSmi(rdx, &miss);
|
| -
|
| - // Check that the map matches.
|
| - __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
|
| - Handle<Map>(receiver->map()));
|
| - __ j(not_equal, &miss);
|
| + __ CheckMap(rdx, receiver_map, &miss, false);
|
|
|
| // Check that the key is a smi.
|
| - __ JumpIfNotSmi(rcx, &miss);
|
| + __ JumpIfNotSmi(rcx, &miss_force_generic);
|
|
|
| // Get the elements array and make sure it is a fast element array, not 'cow'.
|
| __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
|
| __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
|
| factory()->fixed_array_map());
|
| - __ j(not_equal, &miss);
|
| + __ j(not_equal, &miss_force_generic);
|
|
|
| // Check that the key is within bounds.
|
| - if (receiver->IsJSArray()) {
|
| + if (receiver_map->instance_type() == JS_ARRAY_TYPE) {
|
| __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
|
| - __ j(above_equal, &miss);
|
| + __ j(above_equal, &miss_force_generic);
|
| } else {
|
| __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
|
| - __ j(above_equal, &miss);
|
| + __ j(above_equal, &miss_force_generic);
|
| }
|
|
|
| // Do the store and update the write barrier. Make sure to preserve
|
| @@ -2575,11 +2576,43 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized(
|
| Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
| __ jmp(ic, RelocInfo::CODE_TARGET);
|
|
|
| + // Handle store cache miss.
|
| + __ bind(&miss_force_generic);
|
| + Handle<Code> ic_force_generic =
|
| + isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
| + __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
|
| +
|
| // Return the generated code.
|
| return GetCode(NORMAL, NULL);
|
| }
|
|
|
|
|
| +MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
|
| + ZoneMapList* receiver_maps,
|
| + ZoneCodeList* handler_ics) {
|
| + // ----------- S t a t e -------------
|
| + // -- rax : receiver
|
| + // -- rcx : name
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| + Label miss;
|
| + __ JumpIfSmi(rax, &miss);
|
| +
|
| + int receiver_count = receiver_maps->length();
|
| + for (int current = 0; current < receiver_count; ++current) {
|
| + // Check map and tail call if there's a match
|
| + __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), receiver_maps->at(current));
|
| + __ j(equal, handler_ics->at(current), RelocInfo::CODE_TARGET);
|
| + }
|
| + __ bind(&miss);
|
| + Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
| + __ jmp(ic, RelocInfo::CODE_TARGET);
|
| +
|
| + // Return the generated code.
|
| + return GetCode(NORMAL, NULL, MEGAMORPHIC);
|
| +}
|
| +
|
| +
|
| MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
|
| JSObject* object,
|
| JSObject* last) {
|
| @@ -2590,7 +2623,7 @@ MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
|
| // -----------------------------------
|
| Label miss;
|
|
|
| - // Chech that receiver is not a smi.
|
| + // Check that receiver is not a smi.
|
| __ JumpIfSmi(rax, &miss);
|
|
|
| // Check the maps of the full prototype chain. Also check that
|
| @@ -2981,24 +3014,18 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
|
| }
|
|
|
|
|
| -MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) {
|
| +MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(Handle<Map> receiver_map) {
|
| // ----------- S t a t e -------------
|
| // -- rax : key
|
| // -- rdx : receiver
|
| // -- rsp[0] : return address
|
| // -----------------------------------
|
| - Label miss;
|
| -
|
| - // Check that the receiver isn't a smi.
|
| - __ JumpIfSmi(rdx, &miss);
|
| + Label miss, miss_force_generic;
|
|
|
| - // Check that the map matches.
|
| - __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
|
| - Handle<Map>(receiver->map()));
|
| - __ j(not_equal, &miss);
|
| + __ CheckMap(rdx, receiver_map, &miss, false);
|
|
|
| // Check that the key is a smi.
|
| - __ JumpIfNotSmi(rax, &miss);
|
| + __ JumpIfNotSmi(rax, &miss_force_generic);
|
|
|
| // Get the elements array.
|
| __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
|
| @@ -3006,7 +3033,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) {
|
|
|
| // Check that the key is within bounds.
|
| __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
|
| - __ j(above_equal, &miss);
|
| + __ j(above_equal, &miss_force_generic);
|
|
|
| // Load the result and make sure it's not the hole.
|
| SmiIndex index = masm()->SmiToIndex(rbx, rax, kPointerSizeLog2);
|
| @@ -3015,18 +3042,47 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) {
|
| index.scale,
|
| FixedArray::kHeaderSize));
|
| __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
|
| - __ j(equal, &miss);
|
| + __ j(equal, &miss_force_generic);
|
| __ movq(rax, rbx);
|
| __ ret(0);
|
|
|
| __ bind(&miss);
|
| GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
|
|
| + __ bind(&miss_force_generic);
|
| + GenerateKeyedLoadMissForceGeneric(masm());
|
| +
|
| // Return the generated code.
|
| return GetCode(NORMAL, NULL);
|
| }
|
|
|
|
|
| +MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
|
| + ZoneMapList* receiver_maps,
|
| + ZoneCodeList* handler_ics) {
|
| + // ----------- S t a t e -------------
|
| + // -- rax : key
|
| + // -- rdx : receiver
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| + Label miss;
|
| +
|
| + __ JumpIfSmi(rax, &miss);
|
| +
|
| + int receiver_count = receiver_maps->length();
|
| + for (int current = 0; current < receiver_count; ++current) {
|
| + // Check map and tail call if there's a match
|
| + __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), receiver_maps->at(current));
|
| + __ j(equal, handler_ics->at(current), RelocInfo::CODE_TARGET);
|
| + }
|
| + __ bind(&miss);
|
| + GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
| +
|
| + // Return the generated code.
|
| + return GetCode(NORMAL, NULL, MEGAMORPHIC);
|
| +}
|
| +
|
| +
|
| // Specialized stub for constructing objects from functions which only have only
|
| // simple assignments of the form this.x = ...; in their body.
|
| MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
|
| @@ -3167,23 +3223,23 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
|
| // -- rdx : receiver
|
| // -- rsp[0] : return address
|
| // -----------------------------------
|
| - Label slow;
|
| + Label slow, miss;
|
|
|
| // Check that the object isn't a smi.
|
| - __ JumpIfSmi(rdx, &slow);
|
| + __ JumpIfSmi(rdx, &miss);
|
|
|
| // Check that the key is a smi.
|
| - __ JumpIfNotSmi(rax, &slow);
|
| + __ JumpIfNotSmi(rax, &miss);
|
|
|
| // Check that the map matches.
|
| - __ CheckMap(rdx, Handle<Map>(receiver->map()), &slow, false);
|
| + __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, false);
|
| __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
|
|
|
| // Check that the index is in range.
|
| __ SmiToInteger32(rcx, rax);
|
| __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset));
|
| // Unsigned comparison catches both negative and too-large values.
|
| - __ j(above_equal, &slow);
|
| + __ j(above_equal, &miss);
|
|
|
| // rax: index (as a smi)
|
| // rdx: receiver (JSObject)
|
| @@ -3279,13 +3335,19 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
|
| // -- rsp[0] : return address
|
| // -----------------------------------
|
|
|
| - __ pop(rbx);
|
| - __ push(rdx); // receiver
|
| - __ push(rax); // name
|
| - __ push(rbx); // return address
|
| + Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Slow();
|
| + __ jmp(ic, RelocInfo::CODE_TARGET);
|
|
|
| - // Perform tail call to the entry.
|
| - __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
| + // Slow case: Jump to runtime.
|
| + __ bind(&miss);
|
| + // ----------- S t a t e -------------
|
| + // -- rax : key
|
| + // -- rdx : receiver
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| +
|
| + Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss();
|
| + __ jmp(miss_ic, RelocInfo::CODE_TARGET);
|
|
|
| // Return the generated code.
|
| return GetCode(flags);
|
| @@ -3300,23 +3362,26 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
|
| // -- rdx : receiver
|
| // -- rsp[0] : return address
|
| // -----------------------------------
|
| - Label slow;
|
| + Label slow, miss;
|
| +
|
| + // Check that the key is a smi.
|
| + __ JumpIfNotSmi(rcx, &miss);
|
|
|
| // Check that the object isn't a smi.
|
| - __ JumpIfSmi(rdx, &slow);
|
| + __ JumpIfSmi(rdx, &miss);
|
|
|
| // Check that the map matches.
|
| - __ CheckMap(rdx, Handle<Map>(receiver->map()), &slow, false);
|
| + __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, false);
|
| __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
|
|
|
| // Check that the key is a smi.
|
| - __ JumpIfNotSmi(rcx, &slow);
|
| + __ JumpIfNotSmi(rcx, &miss);
|
|
|
| // Check that the index is in range.
|
| __ SmiToInteger32(rdi, rcx); // Untag the index.
|
| __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset));
|
| // Unsigned comparison catches both negative and too-large values.
|
| - __ j(above_equal, &slow);
|
| + __ j(above_equal, &miss);
|
|
|
| // Handle both smis and HeapNumbers in the fast path. Go to the
|
| // runtime for all other kinds of values.
|
| @@ -3450,17 +3515,24 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
|
| // -- rsp[0] : return address
|
| // -----------------------------------
|
|
|
| - __ pop(rbx);
|
| - __ push(rdx); // receiver
|
| - __ push(rcx); // key
|
| - __ push(rax); // value
|
| - __ Push(Smi::FromInt(NONE)); // PropertyAttributes
|
| - __ Push(Smi::FromInt(
|
| - Code::ExtractExtraICStateFromFlags(flags) & kStrictMode));
|
| - __ push(rbx); // return address
|
| + bool strict = (Code::ExtractExtraICStateFromFlags(flags) & kStrictMode) != 0;
|
| + Handle<Code> ic = strict
|
| + ? isolate()->builtins()->KeyedStoreIC_Slow_Strict()
|
| + : isolate()->builtins()->KeyedStoreIC_Slow_NonStrict();
|
| + __ jmp(ic, RelocInfo::CODE_TARGET);
|
| +
|
| + // Miss case: call runtime.
|
| + __ bind(&miss);
|
| +
|
| + // ----------- S t a t e -------------
|
| + // -- rax : value
|
| + // -- rcx : key
|
| + // -- rdx : receiver
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
|
|
| - // Do tail-call to runtime routine.
|
| - __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
|
| + Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
| + __ jmp(miss_ic, RelocInfo::CODE_TARGET);
|
|
|
| return GetCode(flags);
|
| }
|
|
|