Fix Object.prototype.toString.call(proxy)

BUG=

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

Cr-Commit-Position: refs/heads/master@{#32806}
This commit is contained in:
verwaest 2015-12-11 07:56:39 -08:00 committed by Commit bot
parent cf46317483
commit a1e9ccf90f
19 changed files with 47 additions and 69 deletions

View File

@ -1449,7 +1449,7 @@ void MacroAssembler::IsInstanceJSObjectType(Register map,
Ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
// If cmp result is lt, the following ccmp will clear all flags.
// Z == 0, N == V implies gt condition.
Cmp(scratch, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
Cmp(scratch, FIRST_JS_RECEIVER_TYPE);
Ccmp(scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE, NoFlag, ge);
// If we didn't get a valid label object just fall through and leave the

View File

@ -2255,6 +2255,7 @@ void Genesis::InstallJSProxyMaps() {
Handle<Map> proxy_callable_map = Map::Copy(proxy_map, "callable Proxy");
proxy_callable_map->set_is_callable();
native_context()->set_proxy_callable_map(*proxy_callable_map);
proxy_callable_map->SetConstructor(native_context()->function_function());
Handle<Map> proxy_constructor_map =
Map::Copy(proxy_callable_map, "constructor Proxy");
@ -2276,8 +2277,8 @@ void Genesis::InitializeGlobal_harmony_proxies() {
Handle<String> name = factory->Proxy_string();
Handle<Code> code(isolate->builtins()->ProxyConstructor());
Handle<JSFunction> proxy_function =
factory->NewFunction(isolate->proxy_function_map(), name, code);
Handle<JSFunction> proxy_function = factory->NewFunction(
isolate->proxy_function_map(), factory->Object_string(), code);
JSFunction::SetInitialMap(proxy_function,
Handle<Map>(native_context()->proxy_map(), isolate),
@ -2289,7 +2290,7 @@ void Genesis::InitializeGlobal_harmony_proxies() {
proxy_function->shared()->set_length(2);
native_context()->set_proxy_function(*proxy_function);
InstallFunction(global, name, proxy_function, name);
InstallFunction(global, name, proxy_function, factory->Object_string());
}

View File

@ -2542,14 +2542,11 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// Assuming the following assertions, we can use the same compares to test
// for both being a function type and being in the object type range.
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CompareObjectType(input, temp, temp2, FIRST_JS_RECEIVER_TYPE);
__ b(lt, is_false);
__ b(eq, is_true);
__ cmp(temp2, Operand(LAST_JS_RECEIVER_TYPE));
__ b(eq, is_true);
} else {
@ -2557,9 +2554,9 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// actual type and do a signed compare with the width of the type range.
__ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset));
__ ldrb(temp2, FieldMemOperand(temp, Map::kInstanceTypeOffset));
__ sub(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ sub(temp2, temp2, Operand(FIRST_JS_RECEIVER_TYPE));
__ cmp(temp2,
Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - FIRST_JS_RECEIVER_TYPE));
__ b(gt, is_false);
}

View File

@ -2263,8 +2263,6 @@ void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
// Assuming the following assertions, we can use the same compares to test
// for both being a function type and being in the object type range.
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
@ -2272,7 +2270,6 @@ void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
// We expect CompareObjectType to load the object instance type in scratch1.
__ CompareObjectType(input, map, scratch1, FIRST_JS_RECEIVER_TYPE);
__ B(lt, false_label);
__ B(eq, true_label);
__ Cmp(scratch1, LAST_JS_RECEIVER_TYPE);
__ B(eq, true_label);
} else {

View File

@ -2445,14 +2445,11 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// Assuming the following assertions, we can use the same compares to test
// for both being a function type and being in the object type range.
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CmpObjectType(input, FIRST_JS_RECEIVER_TYPE, temp);
__ j(below, is_false);
__ j(equal, is_true);
__ CmpInstanceType(temp, LAST_JS_RECEIVER_TYPE);
__ j(equal, is_true);
} else {
@ -2460,9 +2457,9 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// actual type and do a signed compare with the width of the type range.
__ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
__ movzx_b(temp2, FieldOperand(temp, Map::kInstanceTypeOffset));
__ sub(Operand(temp2), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ sub(Operand(temp2), Immediate(FIRST_JS_RECEIVER_TYPE));
__ cmp(Operand(temp2), Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
FIRST_JS_RECEIVER_TYPE));
__ j(above, is_false);
}

View File

@ -2453,23 +2453,20 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// Assuming the following assertions, we can use the same compares to test
// for both being a function type and being in the object type range.
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ GetObjectType(input, temp, temp2);
__ Branch(is_false, lt, temp2, Operand(FIRST_JS_RECEIVER_TYPE));
__ Branch(is_true, eq, temp2, Operand(FIRST_JS_RECEIVER_TYPE));
__ Branch(is_true, eq, temp2, Operand(LAST_JS_RECEIVER_TYPE));
} else {
// Faster code path to avoid two compares: subtract lower bound from the
// actual type and do a signed compare with the width of the type range.
__ GetObjectType(input, temp, temp2);
__ Subu(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ Subu(temp2, temp2, Operand(FIRST_JS_RECEIVER_TYPE));
__ Branch(is_false, gt, temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
FIRST_JS_RECEIVER_TYPE));
}
// Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.

View File

@ -2574,23 +2574,20 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// Assuming the following assertions, we can use the same compares to test
// for both being a function type and being in the object type range.
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ GetObjectType(input, temp, temp2);
__ Branch(is_false, lt, temp2, Operand(FIRST_JS_RECEIVER_TYPE));
__ Branch(is_true, eq, temp2, Operand(FIRST_JS_RECEIVER_TYPE));
__ Branch(is_true, eq, temp2, Operand(LAST_JS_RECEIVER_TYPE));
} else {
// Faster code path to avoid two compares: subtract lower bound from the
// actual type and do a signed compare with the width of the type range.
__ GetObjectType(input, temp, temp2);
__ Dsubu(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ Dsubu(temp2, temp2, Operand(FIRST_JS_RECEIVER_TYPE));
__ Branch(is_false, gt, temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
FIRST_JS_RECEIVER_TYPE));
}
// Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.

View File

@ -2614,14 +2614,11 @@ void LCodeGen::EmitClassOfTest(Label* is_true, Label* is_false,
// Assuming the following assertions, we can use the same compares to test
// for both being a function type and being in the object type range.
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CompareObjectType(input, temp, temp2, FIRST_JS_RECEIVER_TYPE);
__ blt(is_false);
__ beq(is_true);
__ cmpi(temp2, Operand(LAST_JS_RECEIVER_TYPE));
__ beq(is_true);
} else {
@ -2629,9 +2626,9 @@ void LCodeGen::EmitClassOfTest(Label* is_true, Label* is_false,
// actual type and do a signed compare with the width of the type range.
__ LoadP(temp, FieldMemOperand(input, HeapObject::kMapOffset));
__ lbz(temp2, FieldMemOperand(temp, Map::kInstanceTypeOffset));
__ subi(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ subi(temp2, temp2, Operand(FIRST_JS_RECEIVER_TYPE));
__ cmpi(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
FIRST_JS_RECEIVER_TYPE));
__ bgt(is_false);
}

View File

@ -2502,14 +2502,11 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// Assuming the following assertions, we can use the same compares to test
// for both being a function type and being in the object type range.
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CmpObjectType(input, FIRST_JS_RECEIVER_TYPE, temp);
__ j(below, is_false);
__ j(equal, is_true);
__ CmpInstanceType(temp, LAST_JS_RECEIVER_TYPE);
__ j(equal, is_true);
} else {
@ -2517,9 +2514,9 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// actual type and do a signed compare with the width of the type range.
__ movp(temp, FieldOperand(input, HeapObject::kMapOffset));
__ movzxbl(temp2, FieldOperand(temp, Map::kInstanceTypeOffset));
__ subp(temp2, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ subp(temp2, Immediate(FIRST_JS_RECEIVER_TYPE));
__ cmpp(temp2, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
FIRST_JS_RECEIVER_TYPE));
__ j(above, is_false);
}

View File

@ -2728,14 +2728,11 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// Assuming the following assertions, we can use the same compares to test
// for both being a function type and being in the object type range.
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CmpObjectType(input, FIRST_JS_RECEIVER_TYPE, temp);
__ j(below, is_false);
__ j(equal, is_true);
__ CmpInstanceType(temp, LAST_JS_RECEIVER_TYPE);
__ j(equal, is_true);
} else {
@ -2743,9 +2740,9 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// actual type and do a signed compare with the width of the type range.
__ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
__ movzx_b(temp2, FieldOperand(temp, Map::kInstanceTypeOffset));
__ sub(Operand(temp2), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ sub(Operand(temp2), Immediate(FIRST_JS_RECEIVER_TYPE));
__ cmp(Operand(temp2), Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
FIRST_JS_RECEIVER_TYPE));
__ j(above, is_false);
}

View File

@ -3326,9 +3326,6 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
__ CompareObjectType(r0, r0, r1, FIRST_JS_RECEIVER_TYPE);
// Map is now in r0.
__ b(lt, &null);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
__ b(eq, &function);
__ cmp(r1, Operand(LAST_JS_RECEIVER_TYPE));
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==

View File

@ -3039,9 +3039,6 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
// x10: object's map.
// x11: object's type.
__ B(lt, &null);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
__ B(eq, &function);
__ Cmp(x11, LAST_JS_RECEIVER_TYPE);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==

View File

@ -3209,9 +3209,6 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
__ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, eax);
// Map is now in eax.
__ j(below, &null);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
__ j(equal, &function);
__ CmpInstanceType(eax, LAST_JS_RECEIVER_TYPE);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==

View File

@ -3320,10 +3320,6 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
__ GetObjectType(v0, v0, a1); // Map is now in v0.
__ Branch(&null, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE));
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
__ Branch(&function, eq, a1, Operand(FIRST_JS_RECEIVER_TYPE));
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
__ Branch(&function, eq, a1, Operand(LAST_JS_RECEIVER_TYPE));

View File

@ -3326,10 +3326,6 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
__ GetObjectType(v0, v0, a1); // Map is now in v0.
__ Branch(&null, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE));
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
__ Branch(&function, eq, a1, Operand(FIRST_JS_RECEIVER_TYPE));
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
LAST_JS_RECEIVER_TYPE - 1);
__ Branch(&function, eq, a1, Operand(LAST_JS_RECEIVER_TYPE));

View File

@ -3325,9 +3325,6 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
__ CompareObjectType(r3, r3, r4, FIRST_JS_RECEIVER_TYPE);
// Map is now in r3.
__ blt(&null);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
__ beq(&function);
__ cmpi(r4, Operand(LAST_JS_RECEIVER_TYPE));
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_JS_RECEIVER_TYPE - 1);

View File

@ -3196,9 +3196,6 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
__ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rax);
// Map is now in rax.
__ j(below, &null);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
__ j(equal, &function);
__ CmpInstanceType(rax, LAST_JS_RECEIVER_TYPE);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==

View File

@ -3202,9 +3202,6 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
__ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, eax);
// Map is now in eax.
__ j(below, &null);
STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
FIRST_JS_RECEIVER_TYPE + 1);
__ j(equal, &function);
__ CmpInstanceType(eax, LAST_JS_RECEIVER_TYPE);
STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==

View File

@ -0,0 +1,27 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --harmony-proxies
function test_function(o) {
if (%_ClassOf(o) === "Function") {
return true;
} else {
return false;
}
}
var non_callable = new Proxy({}, {});
var callable = new Proxy(function(){}.__proto__, {});
var constructable = new Proxy(function(){}, {});
assertFalse(test_function(non_callable));
assertTrue(test_function(callable));
assertTrue(test_function(constructable));
%OptimizeFunctionOnNextCall(test_function);
assertFalse(test_function(non_callable));
assertTrue(test_function(callable));
assertTrue(test_function(constructable));