blob: 6d9917de4faca4988ba71c0847c15a5a07e4eabc [file] [log] [blame]
Ben Murdochda12d292016-06-02 14:46:10 +01001// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/interpreter/interpreter-intrinsics.h"
6
7namespace v8 {
8namespace internal {
9namespace interpreter {
10
11using compiler::Node;
12
13#define __ assembler_->
14
15IntrinsicsHelper::IntrinsicsHelper(InterpreterAssembler* assembler)
16 : assembler_(assembler) {}
17
18bool IntrinsicsHelper::IsSupported(Runtime::FunctionId function_id) {
19 switch (function_id) {
20#define SUPPORTED(name, lower_case, count) case Runtime::kInline##name:
21 INTRINSICS_LIST(SUPPORTED)
22 return true;
23#undef SUPPORTED
24 default:
25 return false;
26 }
27}
28
29Node* IntrinsicsHelper::InvokeIntrinsic(Node* function_id, Node* context,
30 Node* first_arg_reg, Node* arg_count) {
31 InterpreterAssembler::Label abort(assembler_), end(assembler_);
32 InterpreterAssembler::Variable result(assembler_,
33 MachineRepresentation::kTagged);
34
35#define MAKE_LABEL(name, lower_case, count) \
36 InterpreterAssembler::Label lower_case(assembler_);
37 INTRINSICS_LIST(MAKE_LABEL)
38#undef MAKE_LABEL
39
40#define LABEL_POINTER(name, lower_case, count) &lower_case,
41 InterpreterAssembler::Label* labels[] = {INTRINSICS_LIST(LABEL_POINTER)};
42#undef LABEL_POINTER
43
44#define CASE(name, lower_case, count) \
45 static_cast<int32_t>(Runtime::kInline##name),
46 int32_t cases[] = {INTRINSICS_LIST(CASE)};
47#undef CASE
48
49 __ Switch(function_id, &abort, cases, labels, arraysize(cases));
50#define HANDLE_CASE(name, lower_case, expected_arg_count) \
51 __ Bind(&lower_case); \
52 if (FLAG_debug_code) { \
53 AbortIfArgCountMismatch(expected_arg_count, arg_count); \
54 } \
55 result.Bind(name(first_arg_reg)); \
56 __ Goto(&end);
57 INTRINSICS_LIST(HANDLE_CASE)
58#undef HANDLE_CASE
59
60 __ Bind(&abort);
61 __ Abort(BailoutReason::kUnexpectedFunctionIDForInvokeIntrinsic);
62 result.Bind(__ UndefinedConstant());
63 __ Goto(&end);
64
65 __ Bind(&end);
66 return result.value();
67}
68
69Node* IntrinsicsHelper::CompareInstanceType(Node* map, int type,
70 InstanceTypeCompareMode mode) {
71 InterpreterAssembler::Variable return_value(assembler_,
72 MachineRepresentation::kTagged);
73 Node* instance_type = __ LoadInstanceType(map);
74
75 InterpreterAssembler::Label if_true(assembler_), if_false(assembler_),
76 end(assembler_);
77 Node* condition;
78 if (mode == kInstanceTypeEqual) {
79 condition = __ Word32Equal(instance_type, __ Int32Constant(type));
80 } else {
81 DCHECK(mode == kInstanceTypeGreaterThanOrEqual);
82 condition =
83 __ Int32GreaterThanOrEqual(instance_type, __ Int32Constant(type));
84 }
85 __ Branch(condition, &if_true, &if_false);
86
87 __ Bind(&if_true);
88 return_value.Bind(__ BooleanConstant(true));
89 __ Goto(&end);
90
91 __ Bind(&if_false);
92 return_value.Bind(__ BooleanConstant(false));
93 __ Goto(&end);
94
95 __ Bind(&end);
96 return return_value.value();
97}
98
99Node* IntrinsicsHelper::IsJSReceiver(Node* input) {
100 InterpreterAssembler::Variable return_value(assembler_,
101 MachineRepresentation::kTagged);
102
103 InterpreterAssembler::Label if_smi(assembler_), if_not_smi(assembler_),
104 end(assembler_);
105 Node* arg = __ LoadRegister(input);
106
107 __ Branch(__ WordIsSmi(arg), &if_smi, &if_not_smi);
108 __ Bind(&if_smi);
109 return_value.Bind(__ BooleanConstant(false));
110 __ Goto(&end);
111
112 __ Bind(&if_not_smi);
113 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
114 return_value.Bind(CompareInstanceType(arg, FIRST_JS_RECEIVER_TYPE,
115 kInstanceTypeGreaterThanOrEqual));
116 __ Goto(&end);
117
118 __ Bind(&end);
119 return return_value.value();
120}
121
122Node* IntrinsicsHelper::IsArray(Node* input) {
123 InterpreterAssembler::Variable return_value(assembler_,
124 MachineRepresentation::kTagged);
125
126 InterpreterAssembler::Label if_smi(assembler_), if_not_smi(assembler_),
127 end(assembler_);
128 Node* arg = __ LoadRegister(input);
129
130 __ Branch(__ WordIsSmi(arg), &if_smi, &if_not_smi);
131 __ Bind(&if_smi);
132 return_value.Bind(__ BooleanConstant(false));
133 __ Goto(&end);
134
135 __ Bind(&if_not_smi);
136 return_value.Bind(
137 CompareInstanceType(arg, JS_ARRAY_TYPE, kInstanceTypeEqual));
138 __ Goto(&end);
139
140 __ Bind(&end);
141 return return_value.value();
142}
143
144void IntrinsicsHelper::AbortIfArgCountMismatch(int expected, Node* actual) {
145 InterpreterAssembler::Label match(assembler_), mismatch(assembler_),
146 end(assembler_);
147 Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected));
148 __ Branch(comparison, &match, &mismatch);
149 __ Bind(&mismatch);
150 __ Abort(kWrongArgumentCountForInvokeIntrinsic);
151 __ Goto(&end);
152 __ Bind(&match);
153 __ Goto(&end);
154 __ Bind(&end);
155}
156
157} // namespace interpreter
158} // namespace internal
159} // namespace v8