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) { ...@@ -1380,24 +1380,35 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
// Loop through the prototype chain looking for the {function} prototype. // Loop through the prototype chain looking for the {function} prototype.
// Assume true, and change to false if not found. // 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; Register const null = scratch;
Label done, loop; Register const result = r0;
__ LoadRoot(r0, Heap::kTrueValueRootIndex); Label done, loop, proxy_case;
__ LoadRoot(result, Heap::kTrueValueRootIndex);
__ LoadRoot(null, Heap::kNullValueRootIndex); __ LoadRoot(null, Heap::kNullValueRootIndex);
__ bind(&loop); __ bind(&loop);
__ ldr(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset)); __ CompareInstanceType(object_map, object_instance_type, JS_PROXY_TYPE);
__ cmp(object_prototype, function_prototype); __ b(eq, &proxy_case);
__ ldr(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
__ cmp(object, function_prototype);
__ b(eq, &done); __ b(eq, &done);
__ cmp(object_prototype, null); __ cmp(object, null);
__ ldr(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset)); __ ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
__ b(ne, &loop); __ b(ne, &loop);
__ LoadRoot(r0, Heap::kFalseValueRootIndex); __ LoadRoot(result, Heap::kFalseValueRootIndex);
__ bind(&done); __ bind(&done);
__ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex);
__ Ret(); __ 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); __ bind(&slow_case);
__ Push(object, function); __ Push(object, function);
__ TailCallRuntime(Runtime::kInstanceOf, 2, 1); __ TailCallRuntime(Runtime::kInstanceOf, 2, 1);
......
...@@ -1585,24 +1585,35 @@ void InstanceOfStub::Generate(MacroAssembler* masm) { ...@@ -1585,24 +1585,35 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
// Loop through the prototype chain looking for the {function} prototype. // Loop through the prototype chain looking for the {function} prototype.
// Assume true, and change to false if not found. // 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; Register const null = scratch;
Label done, loop; Register const result = x0;
__ LoadRoot(x0, Heap::kTrueValueRootIndex); Label done, loop, proxy_case;
__ LoadRoot(result, Heap::kTrueValueRootIndex);
__ LoadRoot(null, Heap::kNullValueRootIndex); __ LoadRoot(null, Heap::kNullValueRootIndex);
__ Bind(&loop); __ Bind(&loop);
__ Ldr(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset)); __ CompareInstanceType(object_map, object_instance_type, JS_PROXY_TYPE);
__ Cmp(object_prototype, function_prototype); __ B(eq, &proxy_case);
__ Ldr(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
__ Cmp(object, function_prototype);
__ B(eq, &done); __ B(eq, &done);
__ Cmp(object_prototype, null); __ Cmp(object, null);
__ Ldr(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset)); __ Ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
__ B(ne, &loop); __ B(ne, &loop);
__ LoadRoot(x0, Heap::kFalseValueRootIndex); __ LoadRoot(result, Heap::kFalseValueRootIndex);
__ Bind(&done); __ Bind(&done);
__ StoreRoot(x0, Heap::kInstanceofCacheAnswerRootIndex); __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex);
__ Ret(); __ 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); __ bind(&slow_case);
__ Push(object, function); __ Push(object, function);
__ TailCallRuntime(Runtime::kInstanceOf, 2, 1); __ TailCallRuntime(Runtime::kInstanceOf, 2, 1);
......
...@@ -895,6 +895,7 @@ class MacroAssembler : public Assembler { ...@@ -895,6 +895,7 @@ class MacroAssembler : public Assembler {
// This is required for compatibility with architecture independant code. // This is required for compatibility with architecture independant code.
// Remove if not needed. // Remove if not needed.
inline void Move(Register dst, Register src) { Mov(dst, src); } inline void Move(Register dst, Register src) { Mov(dst, src); }
inline void Move(Register dst, Smi* src) { Mov(dst, src); }
void LoadInstanceDescriptors(Register map, void LoadInstanceDescriptors(Register map,
Register descriptors); Register descriptors);
......
...@@ -2588,27 +2588,39 @@ void InstanceOfStub::Generate(MacroAssembler* masm) { ...@@ -2588,27 +2588,39 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
// Loop through the prototype chain looking for the {function} prototype. // Loop through the prototype chain looking for the {function} prototype.
// Assume true, and change to false if not found. // Assume true, and change to false if not found.
Register const object_prototype = object_map; Label done, loop, proxy_case;
Label done, loop;
__ mov(eax, isolate()->factory()->true_value()); __ mov(eax, isolate()->factory()->true_value());
__ bind(&loop); __ bind(&loop);
__ mov(object_prototype, FieldOperand(object_map, Map::kPrototypeOffset)); __ CmpInstanceType(object_map, JS_PROXY_TYPE);
__ cmp(object_prototype, function_prototype); __ j(equal, &proxy_case, Label::kNear);
__ mov(object, FieldOperand(object_map, Map::kPrototypeOffset));
__ cmp(object, function_prototype);
__ j(equal, &done, Label::kNear); __ j(equal, &done, Label::kNear);
__ cmp(object_prototype, isolate()->factory()->null_value()); __ cmp(object, isolate()->factory()->null_value());
__ mov(object_map, FieldOperand(object_prototype, HeapObject::kMapOffset)); __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset));
__ j(not_equal, &loop); __ j(not_equal, &loop);
__ mov(eax, isolate()->factory()->false_value()); __ mov(eax, isolate()->factory()->false_value());
__ bind(&done); __ bind(&done);
__ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex);
__ ret(0); __ 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); __ bind(&slow_case);
__ pop(scratch); // Pop return address. __ PopReturnAddressTo(scratch);
__ push(object); // Push {object}. __ Push(object);
__ push(function); // Push {function}. __ Push(function);
__ push(scratch); // Push return address. __ PushReturnAddressFrom(scratch);
__ TailCallRuntime(Runtime::kInstanceOf, 2, 1); __ TailCallRuntime(Runtime::kInstanceOf, 2, 1);
} }
......
...@@ -1505,22 +1505,33 @@ void InstanceOfStub::Generate(MacroAssembler* masm) { ...@@ -1505,22 +1505,33 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
// Loop through the prototype chain looking for the {function} prototype. // Loop through the prototype chain looking for the {function} prototype.
// Assume true, and change to false if not found. // 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; Register const null = scratch;
Label done, loop; Register const result = v0;
__ LoadRoot(v0, Heap::kTrueValueRootIndex); Label done, loop, proxy_case;
__ LoadRoot(result, Heap::kTrueValueRootIndex);
__ LoadRoot(null, Heap::kNullValueRootIndex); __ LoadRoot(null, Heap::kNullValueRootIndex);
__ bind(&loop); __ bind(&loop);
__ lw(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset)); __ lbu(object_instance_type,
__ Branch(&done, eq, object_prototype, Operand(function_prototype)); FieldMemOperand(object_map, Map::kInstanceTypeOffset));
__ Branch(USE_DELAY_SLOT, &loop, ne, object_prototype, Operand(null)); __ Branch(&proxy_case, eq, object_instance_type, Operand(JS_PROXY_TYPE));
__ lw(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset)); __ lw(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
__ LoadRoot(v0, Heap::kFalseValueRootIndex); __ 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); __ bind(&done);
__ Ret(USE_DELAY_SLOT); __ 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); __ bind(&slow_case);
__ Push(object, function); __ Push(object, function);
__ TailCallRuntime(Runtime::kInstanceOf, 2, 1); __ TailCallRuntime(Runtime::kInstanceOf, 2, 1);
......
...@@ -1507,22 +1507,33 @@ void InstanceOfStub::Generate(MacroAssembler* masm) { ...@@ -1507,22 +1507,33 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
// Loop through the prototype chain looking for the {function} prototype. // Loop through the prototype chain looking for the {function} prototype.
// Assume true, and change to false if not found. // 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; Register const null = scratch;
Label done, loop; Register const result = v0;
__ LoadRoot(v0, Heap::kTrueValueRootIndex); Label done, loop, proxy_case;
__ LoadRoot(result, Heap::kTrueValueRootIndex);
__ LoadRoot(null, Heap::kNullValueRootIndex); __ LoadRoot(null, Heap::kNullValueRootIndex);
__ bind(&loop); __ bind(&loop);
__ ld(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset)); __ lbu(object_instance_type,
__ Branch(&done, eq, object_prototype, Operand(function_prototype)); FieldMemOperand(object_map, Map::kInstanceTypeOffset));
__ Branch(USE_DELAY_SLOT, &loop, ne, object_prototype, Operand(null)); __ Branch(&proxy_case, eq, object_instance_type, Operand(JS_PROXY_TYPE));
__ ld(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset)); __ ld(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
__ LoadRoot(v0, Heap::kFalseValueRootIndex); __ 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); __ bind(&done);
__ Ret(USE_DELAY_SLOT); __ 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); __ bind(&slow_case);
__ Push(object, function); __ Push(object, function);
__ TailCallRuntime(Runtime::kInstanceOf, 2, 1); __ TailCallRuntime(Runtime::kInstanceOf, 2, 1);
......
...@@ -2538,22 +2538,34 @@ void InstanceOfStub::Generate(MacroAssembler* masm) { ...@@ -2538,22 +2538,34 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
// Loop through the prototype chain looking for the {function} prototype. // Loop through the prototype chain looking for the {function} prototype.
// Assume true, and change to false if not found. // Assume true, and change to false if not found.
Register const object_prototype = object_map; Label done, loop, proxy_case;
Label done, loop;
__ LoadRoot(rax, Heap::kTrueValueRootIndex); __ LoadRoot(rax, Heap::kTrueValueRootIndex);
__ bind(&loop); __ bind(&loop);
__ movp(object_prototype, FieldOperand(object_map, Map::kPrototypeOffset)); __ CmpInstanceType(object_map, JS_PROXY_TYPE);
__ cmpp(object_prototype, function_prototype); __ j(equal, &proxy_case, Label::kNear);
__ movp(object, FieldOperand(object_map, Map::kPrototypeOffset));
__ cmpp(object, function_prototype);
__ j(equal, &done, Label::kNear); __ j(equal, &done, Label::kNear);
__ CompareRoot(object_prototype, Heap::kNullValueRootIndex); __ CompareRoot(object, Heap::kNullValueRootIndex);
__ movp(object_map, FieldOperand(object_prototype, HeapObject::kMapOffset)); __ movp(object_map, FieldOperand(object, HeapObject::kMapOffset));
__ j(not_equal, &loop); __ j(not_equal, &loop);
__ LoadRoot(rax, Heap::kFalseValueRootIndex); __ LoadRoot(rax, Heap::kFalseValueRootIndex);
__ bind(&done); __ bind(&done);
__ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
__ ret(0); __ 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); __ bind(&slow_case);
__ PopReturnAddressTo(kScratchRegister); __ PopReturnAddressTo(kScratchRegister);
__ Push(object); __ 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