Commit 0e956833 authored by bmeurer's avatar bmeurer Committed by Commit bot

[proxies] InstanceOfStub should bailout to %HasInPrototypeChain for proxies.

Whenever the InstanceOfStub finds a proxy (either passed as object or
somewhere on the prototype chain), it should bailout to the
%HasInPrototypeChain runtime function, which will do the right thing
(soonish).

R=yangguo@chromium.org
BUG=v8:1543
LOG=n

Review URL: https://codereview.chromium.org/1492243003

Cr-Commit-Position: refs/heads/master@{#32549}
parent 440a42b7
......@@ -1380,24 +1380,35 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
// Loop through the prototype chain looking for the {function} prototype.
// Assume true, and change to false if not found.
Register const object_prototype = object_map;
Register const object_instance_type = function_map;
Register const null = scratch;
Label done, loop;
__ LoadRoot(r0, Heap::kTrueValueRootIndex);
Register const result = r0;
Label done, loop, proxy_case;
__ LoadRoot(result, Heap::kTrueValueRootIndex);
__ LoadRoot(null, Heap::kNullValueRootIndex);
__ bind(&loop);
__ ldr(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset));
__ cmp(object_prototype, function_prototype);
__ CompareInstanceType(object_map, object_instance_type, JS_PROXY_TYPE);
__ b(eq, &proxy_case);
__ ldr(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
__ cmp(object, function_prototype);
__ b(eq, &done);
__ cmp(object_prototype, null);
__ ldr(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset));
__ cmp(object, null);
__ ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
__ b(ne, &loop);
__ LoadRoot(r0, Heap::kFalseValueRootIndex);
__ LoadRoot(result, Heap::kFalseValueRootIndex);
__ bind(&done);
__ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
__ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex);
__ Ret();
// Slow-case: Call the runtime function.
// Proxy-case: Call the %HasInPrototypeChain runtime function.
__ bind(&proxy_case);
__ Push(object, function_prototype);
// Invalidate the instanceof cache.
__ Move(scratch, Smi::FromInt(0));
__ StoreRoot(scratch, Heap::kInstanceofCacheFunctionRootIndex);
__ TailCallRuntime(Runtime::kHasInPrototypeChain, 2, 1);
// Slow-case: Call the %InstanceOf runtime function.
__ bind(&slow_case);
__ Push(object, function);
__ TailCallRuntime(Runtime::kInstanceOf, 2, 1);
......
......@@ -1585,24 +1585,35 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
// Loop through the prototype chain looking for the {function} prototype.
// Assume true, and change to false if not found.
Register const object_prototype = object_map;
Register const object_instance_type = function_map;
Register const null = scratch;
Label done, loop;
__ LoadRoot(x0, Heap::kTrueValueRootIndex);
Register const result = x0;
Label done, loop, proxy_case;
__ LoadRoot(result, Heap::kTrueValueRootIndex);
__ LoadRoot(null, Heap::kNullValueRootIndex);
__ Bind(&loop);
__ Ldr(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset));
__ Cmp(object_prototype, function_prototype);
__ CompareInstanceType(object_map, object_instance_type, JS_PROXY_TYPE);
__ B(eq, &proxy_case);
__ Ldr(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
__ Cmp(object, function_prototype);
__ B(eq, &done);
__ Cmp(object_prototype, null);
__ Ldr(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset));
__ Cmp(object, null);
__ Ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
__ B(ne, &loop);
__ LoadRoot(x0, Heap::kFalseValueRootIndex);
__ LoadRoot(result, Heap::kFalseValueRootIndex);
__ Bind(&done);
__ StoreRoot(x0, Heap::kInstanceofCacheAnswerRootIndex);
__ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex);
__ Ret();
// Slow-case: Call the runtime function.
// Proxy-case: Call the %HasInPrototypeChain runtime function.
__ Bind(&proxy_case);
__ Push(object, function_prototype);
// Invalidate the instanceof cache.
__ Move(scratch, Smi::FromInt(0));
__ StoreRoot(scratch, Heap::kInstanceofCacheFunctionRootIndex);
__ TailCallRuntime(Runtime::kHasInPrototypeChain, 2, 1);
// Slow-case: Call the %InstanceOf runtime function.
__ bind(&slow_case);
__ Push(object, function);
__ TailCallRuntime(Runtime::kInstanceOf, 2, 1);
......
......@@ -895,6 +895,7 @@ class MacroAssembler : public Assembler {
// This is required for compatibility with architecture independant code.
// Remove if not needed.
inline void Move(Register dst, Register src) { Mov(dst, src); }
inline void Move(Register dst, Smi* src) { Mov(dst, src); }
void LoadInstanceDescriptors(Register map,
Register descriptors);
......
......@@ -2588,27 +2588,39 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
// Loop through the prototype chain looking for the {function} prototype.
// Assume true, and change to false if not found.
Register const object_prototype = object_map;
Label done, loop;
Label done, loop, proxy_case;
__ mov(eax, isolate()->factory()->true_value());
__ bind(&loop);
__ mov(object_prototype, FieldOperand(object_map, Map::kPrototypeOffset));
__ cmp(object_prototype, function_prototype);
__ CmpInstanceType(object_map, JS_PROXY_TYPE);
__ j(equal, &proxy_case, Label::kNear);
__ mov(object, FieldOperand(object_map, Map::kPrototypeOffset));
__ cmp(object, function_prototype);
__ j(equal, &done, Label::kNear);
__ cmp(object_prototype, isolate()->factory()->null_value());
__ mov(object_map, FieldOperand(object_prototype, HeapObject::kMapOffset));
__ cmp(object, isolate()->factory()->null_value());
__ mov(object_map, FieldOperand(object, HeapObject::kMapOffset));
__ j(not_equal, &loop);
__ mov(eax, isolate()->factory()->false_value());
__ bind(&done);
__ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex);
__ ret(0);
// Slow-case: Call the runtime function.
// Proxy-case: Call the %HasInPrototypeChain runtime function.
__ bind(&proxy_case);
__ PopReturnAddressTo(scratch);
__ Push(object);
__ Push(function_prototype);
__ PushReturnAddressFrom(scratch);
// Invalidate the instanceof cache.
__ Move(eax, Immediate(Smi::FromInt(0)));
__ StoreRoot(eax, scratch, Heap::kInstanceofCacheFunctionRootIndex);
__ TailCallRuntime(Runtime::kHasInPrototypeChain, 2, 1);
// Slow-case: Call the %InstanceOf runtime function.
__ bind(&slow_case);
__ pop(scratch); // Pop return address.
__ push(object); // Push {object}.
__ push(function); // Push {function}.
__ push(scratch); // Push return address.
__ PopReturnAddressTo(scratch);
__ Push(object);
__ Push(function);
__ PushReturnAddressFrom(scratch);
__ TailCallRuntime(Runtime::kInstanceOf, 2, 1);
}
......
......@@ -1505,22 +1505,33 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
// Loop through the prototype chain looking for the {function} prototype.
// Assume true, and change to false if not found.
Register const object_prototype = object_map;
Register const object_instance_type = function_map;
Register const null = scratch;
Label done, loop;
__ LoadRoot(v0, Heap::kTrueValueRootIndex);
Register const result = v0;
Label done, loop, proxy_case;
__ LoadRoot(result, Heap::kTrueValueRootIndex);
__ LoadRoot(null, Heap::kNullValueRootIndex);
__ bind(&loop);
__ lw(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset));
__ Branch(&done, eq, object_prototype, Operand(function_prototype));
__ Branch(USE_DELAY_SLOT, &loop, ne, object_prototype, Operand(null));
__ lw(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset));
__ LoadRoot(v0, Heap::kFalseValueRootIndex);
__ lbu(object_instance_type,
FieldMemOperand(object_map, Map::kInstanceTypeOffset));
__ Branch(&proxy_case, eq, object_instance_type, Operand(JS_PROXY_TYPE));
__ lw(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
__ Branch(&done, eq, object, Operand(function_prototype));
__ Branch(USE_DELAY_SLOT, &loop, ne, object, Operand(null));
__ lw(object_map,
FieldMemOperand(object, HeapObject::kMapOffset)); // In delay slot.
__ LoadRoot(result, Heap::kFalseValueRootIndex);
__ bind(&done);
__ Ret(USE_DELAY_SLOT);
__ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); // In delay slot.
__ StoreRoot(result,
Heap::kInstanceofCacheAnswerRootIndex); // In delay slot.
// Slow-case: Call the runtime function.
// Proxy-case: Call the %HasInPrototypeChain runtime function.
__ bind(&proxy_case);
__ Push(object, function_prototype);
__ TailCallRuntime(Runtime::kHasInPrototypeChain, 2, 1);
// Slow-case: Call the %InstanceOf runtime function.
__ bind(&slow_case);
__ Push(object, function);
__ TailCallRuntime(Runtime::kInstanceOf, 2, 1);
......
......@@ -1507,22 +1507,33 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
// Loop through the prototype chain looking for the {function} prototype.
// Assume true, and change to false if not found.
Register const object_prototype = object_map;
Register const object_instance_type = function_map;
Register const null = scratch;
Label done, loop;
__ LoadRoot(v0, Heap::kTrueValueRootIndex);
Register const result = v0;
Label done, loop, proxy_case;
__ LoadRoot(result, Heap::kTrueValueRootIndex);
__ LoadRoot(null, Heap::kNullValueRootIndex);
__ bind(&loop);
__ ld(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset));
__ Branch(&done, eq, object_prototype, Operand(function_prototype));
__ Branch(USE_DELAY_SLOT, &loop, ne, object_prototype, Operand(null));
__ ld(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset));
__ LoadRoot(v0, Heap::kFalseValueRootIndex);
__ lbu(object_instance_type,
FieldMemOperand(object_map, Map::kInstanceTypeOffset));
__ Branch(&proxy_case, eq, object_instance_type, Operand(JS_PROXY_TYPE));
__ ld(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
__ Branch(&done, eq, object, Operand(function_prototype));
__ Branch(USE_DELAY_SLOT, &loop, ne, object, Operand(null));
__ ld(object_map,
FieldMemOperand(object, HeapObject::kMapOffset)); // In delay slot.
__ LoadRoot(result, Heap::kFalseValueRootIndex);
__ bind(&done);
__ Ret(USE_DELAY_SLOT);
__ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); // In delay slot.
__ StoreRoot(result,
Heap::kInstanceofCacheAnswerRootIndex); // In delay slot.
// Slow-case: Call the runtime function.
// Proxy-case: Call the %HasInPrototypeChain runtime function.
__ bind(&proxy_case);
__ Push(object, function_prototype);
__ TailCallRuntime(Runtime::kHasInPrototypeChain, 2, 1);
// Slow-case: Call the %InstanceOf runtime function.
__ bind(&slow_case);
__ Push(object, function);
__ TailCallRuntime(Runtime::kInstanceOf, 2, 1);
......
......@@ -2538,22 +2538,34 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
// Loop through the prototype chain looking for the {function} prototype.
// Assume true, and change to false if not found.
Register const object_prototype = object_map;
Label done, loop;
Label done, loop, proxy_case;
__ LoadRoot(rax, Heap::kTrueValueRootIndex);
__ bind(&loop);
__ movp(object_prototype, FieldOperand(object_map, Map::kPrototypeOffset));
__ cmpp(object_prototype, function_prototype);
__ CmpInstanceType(object_map, JS_PROXY_TYPE);
__ j(equal, &proxy_case, Label::kNear);
__ movp(object, FieldOperand(object_map, Map::kPrototypeOffset));
__ cmpp(object, function_prototype);
__ j(equal, &done, Label::kNear);
__ CompareRoot(object_prototype, Heap::kNullValueRootIndex);
__ movp(object_map, FieldOperand(object_prototype, HeapObject::kMapOffset));
__ CompareRoot(object, Heap::kNullValueRootIndex);
__ movp(object_map, FieldOperand(object, HeapObject::kMapOffset));
__ j(not_equal, &loop);
__ LoadRoot(rax, Heap::kFalseValueRootIndex);
__ bind(&done);
__ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
__ ret(0);
// Slow-case: Call the runtime function.
// Proxy-case: Call the %HasInPrototypeChain runtime function.
__ bind(&proxy_case);
__ PopReturnAddressTo(kScratchRegister);
__ Push(object);
__ Push(function_prototype);
__ PushReturnAddressFrom(kScratchRegister);
// Invalidate the instanceof cache.
__ Move(rax, Smi::FromInt(0));
__ StoreRoot(rax, Heap::kInstanceofCacheFunctionRootIndex);
__ TailCallRuntime(Runtime::kHasInPrototypeChain, 2, 1);
// Slow-case: Call the %InstanceOf runtime function.
__ bind(&slow_case);
__ PopReturnAddressTo(kScratchRegister);
__ Push(object);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment