Commit f4cf05fc authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Interpreter] Add intrinsics for Is<Type> calls.

Add intrinsics for IsSmi, IsTypedArray, IsRegExp and IsJSProxy,
all of which are intrinsics in Full-Codegen.

BUG=v8:4280
LOG=N

Review-Url: https://codereview.chromium.org/2034493002
Cr-Commit-Position: refs/heads/master@{#36707}
parent dffbcfe8
......@@ -58,9 +58,11 @@ Node* IntrinsicsHelper::InvokeIntrinsic(Node* function_id, Node* context,
#undef HANDLE_CASE
__ Bind(&abort);
__ Abort(BailoutReason::kUnexpectedFunctionIDForInvokeIntrinsic);
result.Bind(__ UndefinedConstant());
__ Goto(&end);
{
__ Abort(BailoutReason::kUnexpectedFunctionIDForInvokeIntrinsic);
result.Bind(__ UndefinedConstant());
__ Goto(&end);
}
__ Bind(&end);
return result.value();
......@@ -85,12 +87,40 @@ Node* IntrinsicsHelper::CompareInstanceType(Node* map, int type,
__ Branch(condition, &if_true, &if_false);
__ Bind(&if_true);
return_value.Bind(__ BooleanConstant(true));
__ Goto(&end);
{
return_value.Bind(__ BooleanConstant(true));
__ Goto(&end);
}
__ Bind(&if_false);
return_value.Bind(__ BooleanConstant(false));
__ Goto(&end);
{
return_value.Bind(__ BooleanConstant(false));
__ Goto(&end);
}
__ Bind(&end);
return return_value.value();
}
Node* IntrinsicsHelper::IsInstanceType(Node* input, int type) {
InterpreterAssembler::Variable return_value(assembler_,
MachineRepresentation::kTagged);
InterpreterAssembler::Label if_smi(assembler_), if_not_smi(assembler_),
end(assembler_);
Node* arg = __ LoadRegister(input);
__ Branch(__ WordIsSmi(arg), &if_smi, &if_not_smi);
__ Bind(&if_smi);
{
return_value.Bind(__ BooleanConstant(false));
__ Goto(&end);
}
__ Bind(&if_not_smi);
{
return_value.Bind(CompareInstanceType(arg, type, kInstanceTypeEqual));
__ Goto(&end);
}
__ Bind(&end);
return return_value.value();
......@@ -100,43 +130,67 @@ Node* IntrinsicsHelper::IsJSReceiver(Node* input, Node* arg_count,
Node* context) {
InterpreterAssembler::Variable return_value(assembler_,
MachineRepresentation::kTagged);
InterpreterAssembler::Label if_smi(assembler_), if_not_smi(assembler_),
end(assembler_);
Node* arg = __ LoadRegister(input);
Node* arg = __ LoadRegister(input);
__ Branch(__ WordIsSmi(arg), &if_smi, &if_not_smi);
__ Bind(&if_smi);
return_value.Bind(__ BooleanConstant(false));
__ Goto(&end);
{
return_value.Bind(__ BooleanConstant(false));
__ Goto(&end);
}
__ Bind(&if_not_smi);
STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
return_value.Bind(CompareInstanceType(arg, FIRST_JS_RECEIVER_TYPE,
kInstanceTypeGreaterThanOrEqual));
__ Goto(&end);
{
STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
return_value.Bind(CompareInstanceType(arg, FIRST_JS_RECEIVER_TYPE,
kInstanceTypeGreaterThanOrEqual));
__ Goto(&end);
}
__ Bind(&end);
return return_value.value();
}
Node* IntrinsicsHelper::IsArray(Node* input, Node* arg_count, Node* context) {
return IsInstanceType(input, JS_ARRAY_TYPE);
}
Node* IntrinsicsHelper::IsJSProxy(Node* input, Node* arg_count, Node* context) {
return IsInstanceType(input, JS_PROXY_TYPE);
}
Node* IntrinsicsHelper::IsRegExp(Node* input, Node* arg_count, Node* context) {
return IsInstanceType(input, JS_REGEXP_TYPE);
}
Node* IntrinsicsHelper::IsTypedArray(Node* input, Node* arg_count,
Node* context) {
return IsInstanceType(input, JS_TYPED_ARRAY_TYPE);
}
Node* IntrinsicsHelper::IsSmi(Node* input, Node* arg_count, Node* context) {
InterpreterAssembler::Variable return_value(assembler_,
MachineRepresentation::kTagged);
InterpreterAssembler::Label if_smi(assembler_), if_not_smi(assembler_),
end(assembler_);
Node* arg = __ LoadRegister(input);
__ Branch(__ WordIsSmi(arg), &if_smi, &if_not_smi);
__ Bind(&if_smi);
return_value.Bind(__ BooleanConstant(false));
__ Goto(&end);
{
return_value.Bind(__ BooleanConstant(true));
__ Goto(&end);
}
__ Bind(&if_not_smi);
return_value.Bind(
CompareInstanceType(arg, JS_ARRAY_TYPE, kInstanceTypeEqual));
__ Goto(&end);
{
return_value.Bind(__ BooleanConstant(false));
__ Goto(&end);
}
__ Bind(&end);
return return_value.value();
......
......@@ -24,8 +24,12 @@ class Node;
// expected number of arguments (-1 denoting argument count is variable).
#define INTRINSICS_LIST(V) \
V(Call, call, -1) \
V(IsArray, is_array, 1) \
V(IsJSProxy, is_js_proxy, 1) \
V(IsJSReceiver, is_js_receiver, 1) \
V(IsArray, is_array, 1)
V(IsRegExp, is_regexp, 1) \
V(IsSmi, is_smi, 1) \
V(IsTypedArray, is_typed_array, 1)
namespace interpreter {
......@@ -45,10 +49,11 @@ class IntrinsicsHelper {
kInstanceTypeEqual,
kInstanceTypeGreaterThanOrEqual
};
compiler::Node* IsInstanceType(compiler::Node* input, int type);
compiler::Node* CompareInstanceType(compiler::Node* map, int type,
InstanceTypeCompareMode mode);
void AbortIfArgCountMismatch(int expected, compiler::Node* actual);
InterpreterAssembler* assembler_;
#define DECLARE_INTRINSIC_HELPER(name, lower_case, count) \
compiler::Node* name(compiler::Node* input, compiler::Node* arg_count, \
......@@ -56,6 +61,8 @@ class IntrinsicsHelper {
INTRINSICS_LIST(DECLARE_INTRINSIC_HELPER)
#undef DECLARE_INTRINSIC_HELPER
InterpreterAssembler* assembler_;
DISALLOW_COPY_AND_ASSIGN(IntrinsicsHelper);
};
......
......@@ -91,6 +91,105 @@ TEST(IsArray) {
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42")));
}
TEST(IsJSProxy) {
HandleAndZoneScope handles;
InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
Runtime::kInlineIsJSProxy);
Factory* factory = handles.main_isolate()->factory();
CHECK_EQ(*factory->false_value(),
*helper.Invoke(helper.NewObject("new Date()")));
CHECK_EQ(*factory->false_value(),
*helper.Invoke(helper.NewObject("(function() {})")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("([1])")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("(/x/)")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
CHECK_EQ(*factory->false_value(),
*helper.Invoke(helper.NewObject("'string'")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42")));
CHECK_EQ(*factory->true_value(),
*helper.Invoke(helper.NewObject("new Proxy({},{})")));
}
TEST(IsRegExp) {
HandleAndZoneScope handles;
InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
Runtime::kInlineIsRegExp);
Factory* factory = handles.main_isolate()->factory();
CHECK_EQ(*factory->false_value(),
*helper.Invoke(helper.NewObject("new Date()")));
CHECK_EQ(*factory->false_value(),
*helper.Invoke(helper.NewObject("(function() {})")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("([1])")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})")));
CHECK_EQ(*factory->true_value(), *helper.Invoke(helper.NewObject("(/x/)")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
CHECK_EQ(*factory->false_value(),
*helper.Invoke(helper.NewObject("'string'")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42")));
}
TEST(IsTypedArray) {
HandleAndZoneScope handles;
InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
Runtime::kInlineIsTypedArray);
Factory* factory = handles.main_isolate()->factory();
CHECK_EQ(*factory->false_value(),
*helper.Invoke(helper.NewObject("new Date()")));
CHECK_EQ(*factory->false_value(),
*helper.Invoke(helper.NewObject("(function() {})")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("([1])")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("(/x/)")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
CHECK_EQ(*factory->false_value(),
*helper.Invoke(helper.NewObject("'string'")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42")));
CHECK_EQ(
*factory->true_value(),
*helper.Invoke(helper.NewObject("new Uint8Array(new ArrayBuffer(1));")));
CHECK_EQ(
*factory->true_value(),
*helper.Invoke(helper.NewObject("new Uint16Array(new ArrayBuffer(2));")));
CHECK_EQ(
*factory->true_value(),
*helper.Invoke(helper.NewObject("new Int32Array(new ArrayBuffer(4));")));
}
TEST(IsSmi) {
HandleAndZoneScope handles;
InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
Runtime::kInlineIsSmi);
Factory* factory = handles.main_isolate()->factory();
CHECK_EQ(*factory->false_value(),
*helper.Invoke(helper.NewObject("new Date()")));
CHECK_EQ(*factory->false_value(),
*helper.Invoke(helper.NewObject("(function() {})")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("([1])")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("(/x/)")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
CHECK_EQ(*factory->false_value(),
*helper.Invoke(helper.NewObject("'string'")));
CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42.2")));
CHECK_EQ(*factory->false_value(),
*helper.Invoke(helper.NewObject("4294967297")));
CHECK_EQ(*factory->true_value(), *helper.Invoke(helper.NewObject("42")));
}
TEST(Call) {
HandleAndZoneScope handles;
Isolate* isolate = handles.main_isolate();
......
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