Fix %FunctionGetName and %_ClassOf for bound functions.
R=bmeurer@chromium.org
BUG=v8:5010
Review-Url: https://codereview.chromium.org/1980463002
Cr-Commit-Position: refs/heads/master@{#36276}
diff --git a/src/crankshaft/arm/lithium-codegen-arm.cc b/src/crankshaft/arm/lithium-codegen-arm.cc
index a87e56a7..340642a 100644
--- a/src/crankshaft/arm/lithium-codegen-arm.cc
+++ b/src/crankshaft/arm/lithium-codegen-arm.cc
@@ -2436,11 +2436,12 @@
__ JumpIfSmi(input, is_false);
- __ CompareObjectType(input, temp, temp2, JS_FUNCTION_TYPE);
+ __ CompareObjectType(input, temp, temp2, FIRST_FUNCTION_TYPE);
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
- __ b(eq, is_true);
+ __ b(hs, is_true);
} else {
- __ b(eq, is_false);
+ __ b(hs, is_false);
}
// Check if the constructor in the map is a function.
diff --git a/src/crankshaft/arm64/lithium-codegen-arm64.cc b/src/crankshaft/arm64/lithium-codegen-arm64.cc
index 049a7bf..ebc5277 100644
--- a/src/crankshaft/arm64/lithium-codegen-arm64.cc
+++ b/src/crankshaft/arm64/lithium-codegen-arm64.cc
@@ -2250,11 +2250,12 @@
__ JumpIfSmi(input, false_label);
Register map = scratch2;
- __ CompareObjectType(input, map, scratch1, JS_FUNCTION_TYPE);
+ __ CompareObjectType(input, map, scratch1, FIRST_FUNCTION_TYPE);
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
- __ B(eq, true_label);
+ __ B(hs, true_label);
} else {
- __ B(eq, false_label);
+ __ B(hs, false_label);
}
// Check if the constructor in the map is a function.
diff --git a/src/crankshaft/ia32/lithium-codegen-ia32.cc b/src/crankshaft/ia32/lithium-codegen-ia32.cc
index b1bcbd4..c7e16c5 100644
--- a/src/crankshaft/ia32/lithium-codegen-ia32.cc
+++ b/src/crankshaft/ia32/lithium-codegen-ia32.cc
@@ -2232,11 +2232,12 @@
DCHECK(!temp.is(temp2));
__ JumpIfSmi(input, is_false);
- __ CmpObjectType(input, JS_FUNCTION_TYPE, temp);
+ __ CmpObjectType(input, FIRST_FUNCTION_TYPE, temp);
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
- __ j(equal, is_true);
+ __ j(above_equal, is_true);
} else {
- __ j(equal, is_false);
+ __ j(above_equal, is_false);
}
// Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
diff --git a/src/crankshaft/mips/lithium-codegen-mips.cc b/src/crankshaft/mips/lithium-codegen-mips.cc
index 79abcda9..bdc5c64 100644
--- a/src/crankshaft/mips/lithium-codegen-mips.cc
+++ b/src/crankshaft/mips/lithium-codegen-mips.cc
@@ -2324,10 +2324,11 @@
__ JumpIfSmi(input, is_false);
__ GetObjectType(input, temp, temp2);
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
- __ Branch(is_true, eq, temp2, Operand(JS_FUNCTION_TYPE));
+ __ Branch(is_true, hs, temp2, Operand(FIRST_FUNCTION_TYPE));
} else {
- __ Branch(is_false, eq, temp2, Operand(JS_FUNCTION_TYPE));
+ __ Branch(is_false, hs, temp2, Operand(FIRST_FUNCTION_TYPE));
}
// Check if the constructor in the map is a function.
diff --git a/src/crankshaft/mips64/lithium-codegen-mips64.cc b/src/crankshaft/mips64/lithium-codegen-mips64.cc
index d2c8b6a..d114e4f 100644
--- a/src/crankshaft/mips64/lithium-codegen-mips64.cc
+++ b/src/crankshaft/mips64/lithium-codegen-mips64.cc
@@ -2443,10 +2443,11 @@
__ JumpIfSmi(input, is_false);
__ GetObjectType(input, temp, temp2);
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
- __ Branch(is_true, eq, temp2, Operand(JS_FUNCTION_TYPE));
+ __ Branch(is_true, hs, temp2, Operand(FIRST_FUNCTION_TYPE));
} else {
- __ Branch(is_false, eq, temp2, Operand(JS_FUNCTION_TYPE));
+ __ Branch(is_false, hs, temp2, Operand(FIRST_FUNCTION_TYPE));
}
// Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
diff --git a/src/crankshaft/x64/lithium-codegen-x64.cc b/src/crankshaft/x64/lithium-codegen-x64.cc
index 301922d..dbabaa5 100644
--- a/src/crankshaft/x64/lithium-codegen-x64.cc
+++ b/src/crankshaft/x64/lithium-codegen-x64.cc
@@ -2381,11 +2381,12 @@
__ JumpIfSmi(input, is_false);
- __ CmpObjectType(input, JS_FUNCTION_TYPE, temp);
+ __ CmpObjectType(input, FIRST_FUNCTION_TYPE, temp);
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
- __ j(equal, is_true);
+ __ j(above_equal, is_true);
} else {
- __ j(equal, is_false);
+ __ j(above_equal, is_false);
}
// Check if the constructor in the map is a function.
diff --git a/src/full-codegen/arm/full-codegen-arm.cc b/src/full-codegen/arm/full-codegen-arm.cc
index d77b7699..1ee6205 100644
--- a/src/full-codegen/arm/full-codegen-arm.cc
+++ b/src/full-codegen/arm/full-codegen-arm.cc
@@ -2834,9 +2834,10 @@
// Map is now in r0.
__ b(lt, &null);
- // Return 'Function' for JSFunction objects.
- __ cmp(r1, Operand(JS_FUNCTION_TYPE));
- __ b(eq, &function);
+ // Return 'Function' for JSFunction and JSBoundFunction objects.
+ __ cmp(r1, Operand(FIRST_FUNCTION_TYPE));
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
+ __ b(hs, &function);
// Check if the constructor in the map is a JS function.
Register instance_type = r2;
diff --git a/src/full-codegen/arm64/full-codegen-arm64.cc b/src/full-codegen/arm64/full-codegen-arm64.cc
index dd48729..ccf57e2 100644
--- a/src/full-codegen/arm64/full-codegen-arm64.cc
+++ b/src/full-codegen/arm64/full-codegen-arm64.cc
@@ -2741,8 +2741,9 @@
__ B(lt, &null);
// Return 'Function' for JSFunction objects.
- __ Cmp(x11, JS_FUNCTION_TYPE);
- __ B(eq, &function);
+ __ Cmp(x11, FIRST_FUNCTION_TYPE);
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
+ __ B(hs, &function);
// Check if the constructor in the map is a JS function.
Register instance_type = x14;
diff --git a/src/full-codegen/ia32/full-codegen-ia32.cc b/src/full-codegen/ia32/full-codegen-ia32.cc
index b86f59a..82e213e 100644
--- a/src/full-codegen/ia32/full-codegen-ia32.cc
+++ b/src/full-codegen/ia32/full-codegen-ia32.cc
@@ -2723,9 +2723,10 @@
__ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, eax);
__ j(below, &null, Label::kNear);
- // Return 'Function' for JSFunction objects.
- __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
- __ j(equal, &function, Label::kNear);
+ // Return 'Function' for JSFunction and JSBoundFunction objects.
+ __ CmpInstanceType(eax, FIRST_FUNCTION_TYPE);
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
+ __ j(above_equal, &function, Label::kNear);
// Check if the constructor in the map is a JS function.
__ GetMapConstructor(eax, eax, ebx);
diff --git a/src/full-codegen/mips/full-codegen-mips.cc b/src/full-codegen/mips/full-codegen-mips.cc
index 65c4e1e..33a7e25 100644
--- a/src/full-codegen/mips/full-codegen-mips.cc
+++ b/src/full-codegen/mips/full-codegen-mips.cc
@@ -2839,8 +2839,9 @@
__ GetObjectType(v0, v0, a1); // Map is now in v0.
__ Branch(&null, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE));
- // Return 'Function' for JSFunction objects.
- __ Branch(&function, eq, a1, Operand(JS_FUNCTION_TYPE));
+ // Return 'Function' for JSFunction and JSBoundFunction objects.
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
+ __ Branch(&function, hs, a1, Operand(FIRST_FUNCTION_TYPE));
// Check if the constructor in the map is a JS function.
Register instance_type = a2;
diff --git a/src/full-codegen/mips64/full-codegen-mips64.cc b/src/full-codegen/mips64/full-codegen-mips64.cc
index 9251210..e2ed637 100644
--- a/src/full-codegen/mips64/full-codegen-mips64.cc
+++ b/src/full-codegen/mips64/full-codegen-mips64.cc
@@ -2838,8 +2838,9 @@
__ GetObjectType(v0, v0, a1); // Map is now in v0.
__ Branch(&null, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE));
- // Return 'Function' for JSFunction objects.
- __ Branch(&function, eq, a1, Operand(JS_FUNCTION_TYPE));
+ // Return 'Function' for JSFunction and JSBoundFunction objects.
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
+ __ Branch(&function, hs, a1, Operand(FIRST_FUNCTION_TYPE));
// Check if the constructor in the map is a JS function.
Register instance_type = a2;
diff --git a/src/full-codegen/x64/full-codegen-x64.cc b/src/full-codegen/x64/full-codegen-x64.cc
index 28a995f..8f05b01 100644
--- a/src/full-codegen/x64/full-codegen-x64.cc
+++ b/src/full-codegen/x64/full-codegen-x64.cc
@@ -2712,9 +2712,10 @@
__ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rax);
__ j(below, &null, Label::kNear);
- // Return 'Function' for JSFunction objects.
- __ CmpInstanceType(rax, JS_FUNCTION_TYPE);
- __ j(equal, &function, Label::kNear);
+ // Return 'Function' for JSFunction and JSBoundFunction objects.
+ __ CmpInstanceType(rax, FIRST_FUNCTION_TYPE);
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
+ __ j(above_equal, &function, Label::kNear);
// Check if the constructor in the map is a JS function.
__ GetMapConstructor(rax, rax, rbx);
diff --git a/src/runtime/runtime-function.cc b/src/runtime/runtime-function.cc
index 7d7b811..56cf3b6 100644
--- a/src/runtime/runtime-function.cc
+++ b/src/runtime/runtime-function.cc
@@ -17,11 +17,19 @@
namespace internal {
RUNTIME_FUNCTION(Runtime_FunctionGetName) {
- SealHandleScope shs(isolate);
+ HandleScope scope(isolate);
DCHECK(args.length() == 1);
- CONVERT_ARG_CHECKED(JSFunction, f, 0);
- return f->shared()->name();
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
+ Handle<Object> result;
+ if (function->IsJSBoundFunction()) {
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, JSBoundFunction::GetName(
+ isolate, Handle<JSBoundFunction>::cast(function)));
+ } else {
+ result = JSFunction::GetName(isolate, Handle<JSFunction>::cast(function));
+ }
+ return *result;
}
diff --git a/test/mjsunit/mirror-function.js b/test/mjsunit/mirror-function.js
index cda815d..88106a2 100644
--- a/test/mjsunit/mirror-function.js
+++ b/test/mjsunit/mirror-function.js
@@ -88,3 +88,4 @@
testFunctionMirror(function(){});
testFunctionMirror(function a(){return 1;});
testFunctionMirror(Math.sin);
+testFunctionMirror((function(){}).bind({}), "Object");
diff --git a/test/mjsunit/regress/regress-5010.js b/test/mjsunit/regress/regress-5010.js
new file mode 100644
index 0000000..ecd4026
--- /dev/null
+++ b/test/mjsunit/regress/regress-5010.js
@@ -0,0 +1,9 @@
+// Copyright 2016 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
+
+var bound = (function(){}).bind({});
+assertEquals("Function", %_ClassOf(bound));
+assertEquals("Function", %ClassOf(bound));