interpreter-intrinsics.cc revision 1b268ca467c924004286c97bac133db489cf43d0
1// 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
160