Index: src/interpreter/interpreter-intrinsics.cc |
diff --git a/src/interpreter/interpreter-intrinsics.cc b/src/interpreter/interpreter-intrinsics.cc |
index fc7cfc766d5dcb306bac06b0ef056a56f3f9d181..ae8e83a8267ba8d5cdb532ba5ecafd3c30b5607a 100644 |
--- a/src/interpreter/interpreter-intrinsics.cc |
+++ b/src/interpreter/interpreter-intrinsics.cc |
@@ -103,11 +103,11 @@ Node* IntrinsicsHelper::InvokeIntrinsic(Node* function_id, Node* context, |
return result.value(); |
} |
-Node* IntrinsicsHelper::CompareInstanceType(Node* map, int type, |
+Node* IntrinsicsHelper::CompareInstanceType(Node* object, int type, |
InstanceTypeCompareMode mode) { |
InterpreterAssembler::Variable return_value(assembler_, |
MachineRepresentation::kTagged); |
- Node* instance_type = __ LoadInstanceType(map); |
+ Node* instance_type = __ LoadInstanceType(object); |
InterpreterAssembler::Label if_true(assembler_), if_false(assembler_), |
end(assembler_); |
@@ -340,6 +340,66 @@ Node* IntrinsicsHelper::ValueOf(Node* args_reg, Node* arg_count, |
return return_value.value(); |
} |
+Node* IntrinsicsHelper::ClassOf(Node* args_reg, Node* arg_count, |
+ Node* context) { |
+ InterpreterAssembler::Variable return_value(assembler_, |
+ MachineRepresentation::kTagged); |
+ InterpreterAssembler::Label done(assembler_), null(assembler_), |
+ function(assembler_), non_function_constructor(assembler_); |
+ |
+ Node* object = __ LoadRegister(args_reg); |
+ |
+ // If the object is not a JSReceiver, we return null. |
+ __ GotoIf(__ WordIsSmi(object), &null); |
+ STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
+ Node* is_js_receiver = CompareInstanceType(object, FIRST_JS_RECEIVER_TYPE, |
+ kInstanceTypeGreaterThanOrEqual); |
+ __ GotoUnless(is_js_receiver, &null); |
+ |
+ // Return 'Function' for JSFunction and JSBoundFunction objects. |
+ Node* is_function = CompareInstanceType(object, FIRST_FUNCTION_TYPE, |
+ kInstanceTypeGreaterThanOrEqual); |
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); |
+ __ GotoIf(is_function, &function); |
+ |
+ // Check if the constructor in the map is a JS function. |
+ Node* constructor = __ LoadMapConstructor(__ LoadMap(object)); |
+ Node* constructor_is_js_function = |
+ CompareInstanceType(constructor, JS_FUNCTION_TYPE, kInstanceTypeEqual); |
+ __ GotoUnless(constructor_is_js_function, &non_function_constructor); |
+ |
+ // Grab the instance class name from the constructor function. |
+ Node* shared = |
+ __ LoadObjectField(constructor, JSFunction::kSharedFunctionInfoOffset); |
+ return_value.Bind( |
+ __ LoadObjectField(shared, SharedFunctionInfo::kInstanceClassNameOffset)); |
+ __ Goto(&done); |
+ |
+ // Non-JS objects have class null. |
+ __ Bind(&null); |
+ { |
+ return_value.Bind(__ LoadRoot(Heap::kNullValueRootIndex)); |
+ __ Goto(&done); |
+ } |
+ |
+ // Functions have class 'Function'. |
+ __ Bind(&function); |
+ { |
+ return_value.Bind(__ LoadRoot(Heap::kFunction_stringRootIndex)); |
+ __ Goto(&done); |
+ } |
+ |
+ // Objects with a non-function constructor have class 'Object'. |
+ __ Bind(&non_function_constructor); |
+ { |
+ return_value.Bind(__ LoadRoot(Heap::kObject_stringRootIndex)); |
+ __ Goto(&done); |
+ } |
+ |
+ __ Bind(&done); |
+ return return_value.value(); |
+} |
+ |
void IntrinsicsHelper::AbortIfArgCountMismatch(int expected, Node* actual) { |
InterpreterAssembler::Label match(assembler_); |
Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected)); |