| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2017 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/interpreter/interpreter-intrinsics-generator.h" |
| 6 |
| 7 #include "src/allocation.h" |
| 8 #include "src/builtins/builtins.h" |
| 9 #include "src/code-factory.h" |
| 10 #include "src/frames.h" |
| 11 #include "src/interpreter/bytecodes.h" |
| 12 #include "src/interpreter/interpreter-assembler.h" |
| 5 #include "src/interpreter/interpreter-intrinsics.h" | 13 #include "src/interpreter/interpreter-intrinsics.h" |
| 6 | 14 |
| 7 #include "src/code-factory.h" | |
| 8 #include "src/objects-inl.h" | |
| 9 | |
| 10 namespace v8 { | 15 namespace v8 { |
| 11 namespace internal { | 16 namespace internal { |
| 12 namespace interpreter { | 17 namespace interpreter { |
| 13 | 18 |
| 14 using compiler::Node; | 19 using compiler::Node; |
| 15 | 20 |
| 21 class IntrinsicsGenerator { |
| 22 public: |
| 23 explicit IntrinsicsGenerator(InterpreterAssembler* assembler) |
| 24 : isolate_(assembler->isolate()), |
| 25 zone_(assembler->zone()), |
| 26 assembler_(assembler) {} |
| 27 |
| 28 Node* InvokeIntrinsic(Node* function_id, Node* context, Node* first_arg_reg, |
| 29 Node* arg_count); |
| 30 |
| 31 private: |
| 32 enum InstanceTypeCompareMode { |
| 33 kInstanceTypeEqual, |
| 34 kInstanceTypeGreaterThanOrEqual |
| 35 }; |
| 36 |
| 37 Node* IsInstanceType(Node* input, int type); |
| 38 Node* CompareInstanceType(Node* map, int type, InstanceTypeCompareMode mode); |
| 39 Node* IntrinsicAsStubCall(Node* input, Node* context, |
| 40 Callable const& callable); |
| 41 void AbortIfArgCountMismatch(int expected, compiler::Node* actual); |
| 42 |
| 43 #define DECLARE_INTRINSIC_HELPER(name, lower_case, count) \ |
| 44 Node* name(Node* input, Node* arg_count, Node* context); |
| 45 INTRINSICS_LIST(DECLARE_INTRINSIC_HELPER) |
| 46 #undef DECLARE_INTRINSIC_HELPER |
| 47 |
| 48 Isolate* isolate() { return isolate_; } |
| 49 Zone* zone() { return zone_; } |
| 50 |
| 51 Isolate* isolate_; |
| 52 Zone* zone_; |
| 53 InterpreterAssembler* assembler_; |
| 54 |
| 55 DISALLOW_COPY_AND_ASSIGN(IntrinsicsGenerator); |
| 56 }; |
| 57 |
| 58 Node* GenerateInvokeIntrinsic(InterpreterAssembler* assembler, |
| 59 Node* function_id, Node* context, |
| 60 Node* first_arg_reg, Node* arg_count) { |
| 61 IntrinsicsGenerator generator(assembler); |
| 62 return generator.InvokeIntrinsic(function_id, context, first_arg_reg, |
| 63 arg_count); |
| 64 } |
| 65 |
| 16 #define __ assembler_-> | 66 #define __ assembler_-> |
| 17 | 67 |
| 18 IntrinsicsHelper::IntrinsicsHelper(InterpreterAssembler* assembler) | 68 Node* IntrinsicsGenerator::InvokeIntrinsic(Node* function_id, Node* context, |
| 19 : isolate_(assembler->isolate()), | 69 Node* first_arg_reg, |
| 20 zone_(assembler->zone()), | 70 Node* arg_count) { |
| 21 assembler_(assembler) {} | |
| 22 | |
| 23 // static | |
| 24 bool IntrinsicsHelper::IsSupported(Runtime::FunctionId function_id) { | |
| 25 switch (function_id) { | |
| 26 #define SUPPORTED(name, lower_case, count) case Runtime::kInline##name: | |
| 27 INTRINSICS_LIST(SUPPORTED) | |
| 28 return true; | |
| 29 #undef SUPPORTED | |
| 30 default: | |
| 31 return false; | |
| 32 } | |
| 33 } | |
| 34 | |
| 35 // static | |
| 36 IntrinsicsHelper::IntrinsicId IntrinsicsHelper::FromRuntimeId( | |
| 37 Runtime::FunctionId function_id) { | |
| 38 switch (function_id) { | |
| 39 #define TO_RUNTIME_ID(name, lower_case, count) \ | |
| 40 case Runtime::kInline##name: \ | |
| 41 return IntrinsicId::k##name; | |
| 42 INTRINSICS_LIST(TO_RUNTIME_ID) | |
| 43 #undef TO_RUNTIME_ID | |
| 44 default: | |
| 45 UNREACHABLE(); | |
| 46 return static_cast<IntrinsicsHelper::IntrinsicId>(-1); | |
| 47 } | |
| 48 } | |
| 49 | |
| 50 // static | |
| 51 Runtime::FunctionId IntrinsicsHelper::ToRuntimeId( | |
| 52 IntrinsicsHelper::IntrinsicId intrinsic_id) { | |
| 53 switch (intrinsic_id) { | |
| 54 #define TO_INTRINSIC_ID(name, lower_case, count) \ | |
| 55 case IntrinsicId::k##name: \ | |
| 56 return Runtime::kInline##name; | |
| 57 INTRINSICS_LIST(TO_INTRINSIC_ID) | |
| 58 #undef TO_INTRINSIC_ID | |
| 59 default: | |
| 60 UNREACHABLE(); | |
| 61 return static_cast<Runtime::FunctionId>(-1); | |
| 62 } | |
| 63 } | |
| 64 | |
| 65 Node* IntrinsicsHelper::InvokeIntrinsic(Node* function_id, Node* context, | |
| 66 Node* first_arg_reg, Node* arg_count) { | |
| 67 InterpreterAssembler::Label abort(assembler_), end(assembler_); | 71 InterpreterAssembler::Label abort(assembler_), end(assembler_); |
| 68 InterpreterAssembler::Variable result(assembler_, | 72 InterpreterAssembler::Variable result(assembler_, |
| 69 MachineRepresentation::kTagged); | 73 MachineRepresentation::kTagged); |
| 70 | 74 |
| 71 #define MAKE_LABEL(name, lower_case, count) \ | 75 #define MAKE_LABEL(name, lower_case, count) \ |
| 72 InterpreterAssembler::Label lower_case(assembler_); | 76 InterpreterAssembler::Label lower_case(assembler_); |
| 73 INTRINSICS_LIST(MAKE_LABEL) | 77 INTRINSICS_LIST(MAKE_LABEL) |
| 74 #undef MAKE_LABEL | 78 #undef MAKE_LABEL |
| 75 | 79 |
| 76 #define LABEL_POINTER(name, lower_case, count) &lower_case, | 80 #define LABEL_POINTER(name, lower_case, count) &lower_case, |
| 77 InterpreterAssembler::Label* labels[] = {INTRINSICS_LIST(LABEL_POINTER)}; | 81 InterpreterAssembler::Label* labels[] = {INTRINSICS_LIST(LABEL_POINTER)}; |
| 78 #undef LABEL_POINTER | 82 #undef LABEL_POINTER |
| 79 | 83 |
| 80 #define CASE(name, lower_case, count) \ | 84 #define CASE(name, lower_case, count) \ |
| 81 static_cast<int32_t>(IntrinsicId::k##name), | 85 static_cast<int32_t>(IntrinsicsHelper::IntrinsicId::k##name), |
| 82 int32_t cases[] = {INTRINSICS_LIST(CASE)}; | 86 int32_t cases[] = {INTRINSICS_LIST(CASE)}; |
| 83 #undef CASE | 87 #undef CASE |
| 84 | 88 |
| 85 __ Switch(function_id, &abort, cases, labels, arraysize(cases)); | 89 __ Switch(function_id, &abort, cases, labels, arraysize(cases)); |
| 86 #define HANDLE_CASE(name, lower_case, expected_arg_count) \ | 90 #define HANDLE_CASE(name, lower_case, expected_arg_count) \ |
| 87 __ Bind(&lower_case); \ | 91 __ Bind(&lower_case); \ |
| 88 if (FLAG_debug_code && expected_arg_count >= 0) { \ | 92 if (FLAG_debug_code && expected_arg_count >= 0) { \ |
| 89 AbortIfArgCountMismatch(expected_arg_count, arg_count); \ | 93 AbortIfArgCountMismatch(expected_arg_count, arg_count); \ |
| 90 } \ | 94 } \ |
| 91 result.Bind(name(first_arg_reg, arg_count, context)); \ | 95 result.Bind(name(first_arg_reg, arg_count, context)); \ |
| 92 __ Goto(&end); | 96 __ Goto(&end); |
| 93 INTRINSICS_LIST(HANDLE_CASE) | 97 INTRINSICS_LIST(HANDLE_CASE) |
| 94 #undef HANDLE_CASE | 98 #undef HANDLE_CASE |
| 95 | 99 |
| 96 __ Bind(&abort); | 100 __ Bind(&abort); |
| 97 { | 101 { |
| 98 __ Abort(BailoutReason::kUnexpectedFunctionIDForInvokeIntrinsic); | 102 __ Abort(BailoutReason::kUnexpectedFunctionIDForInvokeIntrinsic); |
| 99 result.Bind(__ UndefinedConstant()); | 103 result.Bind(__ UndefinedConstant()); |
| 100 __ Goto(&end); | 104 __ Goto(&end); |
| 101 } | 105 } |
| 102 | 106 |
| 103 __ Bind(&end); | 107 __ Bind(&end); |
| 104 return result.value(); | 108 return result.value(); |
| 105 } | 109 } |
| 106 | 110 |
| 107 Node* IntrinsicsHelper::CompareInstanceType(Node* object, int type, | 111 Node* IntrinsicsGenerator::CompareInstanceType(Node* object, int type, |
| 108 InstanceTypeCompareMode mode) { | 112 InstanceTypeCompareMode mode) { |
| 109 Node* instance_type = __ LoadInstanceType(object); | 113 Node* instance_type = __ LoadInstanceType(object); |
| 110 | 114 |
| 111 if (mode == kInstanceTypeEqual) { | 115 if (mode == kInstanceTypeEqual) { |
| 112 return __ Word32Equal(instance_type, __ Int32Constant(type)); | 116 return __ Word32Equal(instance_type, __ Int32Constant(type)); |
| 113 } else { | 117 } else { |
| 114 DCHECK(mode == kInstanceTypeGreaterThanOrEqual); | 118 DCHECK(mode == kInstanceTypeGreaterThanOrEqual); |
| 115 return __ Int32GreaterThanOrEqual(instance_type, __ Int32Constant(type)); | 119 return __ Int32GreaterThanOrEqual(instance_type, __ Int32Constant(type)); |
| 116 } | 120 } |
| 117 } | 121 } |
| 118 | 122 |
| 119 Node* IntrinsicsHelper::IsInstanceType(Node* input, int type) { | 123 Node* IntrinsicsGenerator::IsInstanceType(Node* input, int type) { |
| 120 InterpreterAssembler::Variable return_value(assembler_, | 124 InterpreterAssembler::Variable return_value(assembler_, |
| 121 MachineRepresentation::kTagged); | 125 MachineRepresentation::kTagged); |
| 122 // TODO(ishell): Use Select here. | 126 // TODO(ishell): Use Select here. |
| 123 InterpreterAssembler::Label if_not_smi(assembler_), return_true(assembler_), | 127 InterpreterAssembler::Label if_not_smi(assembler_), return_true(assembler_), |
| 124 return_false(assembler_), end(assembler_); | 128 return_false(assembler_), end(assembler_); |
| 125 Node* arg = __ LoadRegister(input); | 129 Node* arg = __ LoadRegister(input); |
| 126 __ GotoIf(__ TaggedIsSmi(arg), &return_false); | 130 __ GotoIf(__ TaggedIsSmi(arg), &return_false); |
| 127 | 131 |
| 128 Node* condition = CompareInstanceType(arg, type, kInstanceTypeEqual); | 132 Node* condition = CompareInstanceType(arg, type, kInstanceTypeEqual); |
| 129 __ Branch(condition, &return_true, &return_false); | 133 __ Branch(condition, &return_true, &return_false); |
| 130 | 134 |
| 131 __ Bind(&return_true); | 135 __ Bind(&return_true); |
| 132 { | 136 { |
| 133 return_value.Bind(__ BooleanConstant(true)); | 137 return_value.Bind(__ BooleanConstant(true)); |
| 134 __ Goto(&end); | 138 __ Goto(&end); |
| 135 } | 139 } |
| 136 | 140 |
| 137 __ Bind(&return_false); | 141 __ Bind(&return_false); |
| 138 { | 142 { |
| 139 return_value.Bind(__ BooleanConstant(false)); | 143 return_value.Bind(__ BooleanConstant(false)); |
| 140 __ Goto(&end); | 144 __ Goto(&end); |
| 141 } | 145 } |
| 142 | 146 |
| 143 __ Bind(&end); | 147 __ Bind(&end); |
| 144 return return_value.value(); | 148 return return_value.value(); |
| 145 } | 149 } |
| 146 | 150 |
| 147 Node* IntrinsicsHelper::IsJSReceiver(Node* input, Node* arg_count, | 151 Node* IntrinsicsGenerator::IsJSReceiver(Node* input, Node* arg_count, |
| 148 Node* context) { | 152 Node* context) { |
| 149 // TODO(ishell): Use Select here. | 153 // TODO(ishell): Use Select here. |
| 150 // TODO(ishell): Use CSA::IsJSReceiverInstanceType here. | 154 // TODO(ishell): Use CSA::IsJSReceiverInstanceType here. |
| 151 InterpreterAssembler::Variable return_value(assembler_, | 155 InterpreterAssembler::Variable return_value(assembler_, |
| 152 MachineRepresentation::kTagged); | 156 MachineRepresentation::kTagged); |
| 153 InterpreterAssembler::Label return_true(assembler_), return_false(assembler_), | 157 InterpreterAssembler::Label return_true(assembler_), return_false(assembler_), |
| 154 end(assembler_); | 158 end(assembler_); |
| 155 | 159 |
| 156 Node* arg = __ LoadRegister(input); | 160 Node* arg = __ LoadRegister(input); |
| 157 __ GotoIf(__ TaggedIsSmi(arg), &return_false); | 161 __ GotoIf(__ TaggedIsSmi(arg), &return_false); |
| 158 | 162 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 170 __ Bind(&return_false); | 174 __ Bind(&return_false); |
| 171 { | 175 { |
| 172 return_value.Bind(__ BooleanConstant(false)); | 176 return_value.Bind(__ BooleanConstant(false)); |
| 173 __ Goto(&end); | 177 __ Goto(&end); |
| 174 } | 178 } |
| 175 | 179 |
| 176 __ Bind(&end); | 180 __ Bind(&end); |
| 177 return return_value.value(); | 181 return return_value.value(); |
| 178 } | 182 } |
| 179 | 183 |
| 180 Node* IntrinsicsHelper::IsArray(Node* input, Node* arg_count, Node* context) { | 184 Node* IntrinsicsGenerator::IsArray(Node* input, Node* arg_count, |
| 185 Node* context) { |
| 181 return IsInstanceType(input, JS_ARRAY_TYPE); | 186 return IsInstanceType(input, JS_ARRAY_TYPE); |
| 182 } | 187 } |
| 183 | 188 |
| 184 Node* IntrinsicsHelper::IsJSProxy(Node* input, Node* arg_count, Node* context) { | 189 Node* IntrinsicsGenerator::IsJSProxy(Node* input, Node* arg_count, |
| 190 Node* context) { |
| 185 return IsInstanceType(input, JS_PROXY_TYPE); | 191 return IsInstanceType(input, JS_PROXY_TYPE); |
| 186 } | 192 } |
| 187 | 193 |
| 188 Node* IntrinsicsHelper::IsTypedArray(Node* input, Node* arg_count, | 194 Node* IntrinsicsGenerator::IsTypedArray(Node* input, Node* arg_count, |
| 189 Node* context) { | 195 Node* context) { |
| 190 return IsInstanceType(input, JS_TYPED_ARRAY_TYPE); | 196 return IsInstanceType(input, JS_TYPED_ARRAY_TYPE); |
| 191 } | 197 } |
| 192 | 198 |
| 193 Node* IntrinsicsHelper::IsSmi(Node* input, Node* arg_count, Node* context) { | 199 Node* IntrinsicsGenerator::IsSmi(Node* input, Node* arg_count, Node* context) { |
| 194 // TODO(ishell): Use SelectBooleanConstant here. | 200 // TODO(ishell): Use SelectBooleanConstant here. |
| 195 InterpreterAssembler::Variable return_value(assembler_, | 201 InterpreterAssembler::Variable return_value(assembler_, |
| 196 MachineRepresentation::kTagged); | 202 MachineRepresentation::kTagged); |
| 197 InterpreterAssembler::Label if_smi(assembler_), if_not_smi(assembler_), | 203 InterpreterAssembler::Label if_smi(assembler_), if_not_smi(assembler_), |
| 198 end(assembler_); | 204 end(assembler_); |
| 199 | 205 |
| 200 Node* arg = __ LoadRegister(input); | 206 Node* arg = __ LoadRegister(input); |
| 201 | 207 |
| 202 __ Branch(__ TaggedIsSmi(arg), &if_smi, &if_not_smi); | 208 __ Branch(__ TaggedIsSmi(arg), &if_smi, &if_not_smi); |
| 203 __ Bind(&if_smi); | 209 __ Bind(&if_smi); |
| 204 { | 210 { |
| 205 return_value.Bind(__ BooleanConstant(true)); | 211 return_value.Bind(__ BooleanConstant(true)); |
| 206 __ Goto(&end); | 212 __ Goto(&end); |
| 207 } | 213 } |
| 208 | 214 |
| 209 __ Bind(&if_not_smi); | 215 __ Bind(&if_not_smi); |
| 210 { | 216 { |
| 211 return_value.Bind(__ BooleanConstant(false)); | 217 return_value.Bind(__ BooleanConstant(false)); |
| 212 __ Goto(&end); | 218 __ Goto(&end); |
| 213 } | 219 } |
| 214 | 220 |
| 215 __ Bind(&end); | 221 __ Bind(&end); |
| 216 return return_value.value(); | 222 return return_value.value(); |
| 217 } | 223 } |
| 218 | 224 |
| 219 Node* IntrinsicsHelper::IntrinsicAsStubCall(Node* args_reg, Node* context, | 225 Node* IntrinsicsGenerator::IntrinsicAsStubCall(Node* args_reg, Node* context, |
| 220 Callable const& callable) { | 226 Callable const& callable) { |
| 221 int param_count = callable.descriptor().GetParameterCount(); | 227 int param_count = callable.descriptor().GetParameterCount(); |
| 222 int input_count = param_count + 2; // +2 for target and context | 228 int input_count = param_count + 2; // +2 for target and context |
| 223 Node** args = zone()->NewArray<Node*>(input_count); | 229 Node** args = zone()->NewArray<Node*>(input_count); |
| 224 int index = 0; | 230 int index = 0; |
| 225 args[index++] = __ HeapConstant(callable.code()); | 231 args[index++] = __ HeapConstant(callable.code()); |
| 226 for (int i = 0; i < param_count; i++) { | 232 for (int i = 0; i < param_count; i++) { |
| 227 args[index++] = __ LoadRegister(args_reg); | 233 args[index++] = __ LoadRegister(args_reg); |
| 228 args_reg = __ NextRegister(args_reg); | 234 args_reg = __ NextRegister(args_reg); |
| 229 } | 235 } |
| 230 args[index++] = context; | 236 args[index++] = context; |
| 231 return __ CallStubN(callable.descriptor(), 1, input_count, args); | 237 return __ CallStubN(callable.descriptor(), 1, input_count, args); |
| 232 } | 238 } |
| 233 | 239 |
| 234 Node* IntrinsicsHelper::CreateIterResultObject(Node* input, Node* arg_count, | 240 Node* IntrinsicsGenerator::CreateIterResultObject(Node* input, Node* arg_count, |
| 235 Node* context) { | 241 Node* context) { |
| 236 return IntrinsicAsStubCall(input, context, | 242 return IntrinsicAsStubCall(input, context, |
| 237 CodeFactory::CreateIterResultObject(isolate())); | 243 CodeFactory::CreateIterResultObject(isolate())); |
| 238 } | 244 } |
| 239 | 245 |
| 240 Node* IntrinsicsHelper::HasProperty(Node* input, Node* arg_count, | 246 Node* IntrinsicsGenerator::HasProperty(Node* input, Node* arg_count, |
| 241 Node* context) { | 247 Node* context) { |
| 242 return IntrinsicAsStubCall(input, context, | 248 return IntrinsicAsStubCall(input, context, |
| 243 CodeFactory::HasProperty(isolate())); | 249 CodeFactory::HasProperty(isolate())); |
| 244 } | 250 } |
| 245 | 251 |
| 246 Node* IntrinsicsHelper::SubString(Node* input, Node* arg_count, Node* context) { | 252 Node* IntrinsicsGenerator::SubString(Node* input, Node* arg_count, |
| 253 Node* context) { |
| 247 return IntrinsicAsStubCall(input, context, CodeFactory::SubString(isolate())); | 254 return IntrinsicAsStubCall(input, context, CodeFactory::SubString(isolate())); |
| 248 } | 255 } |
| 249 | 256 |
| 250 Node* IntrinsicsHelper::ToString(Node* input, Node* arg_count, Node* context) { | 257 Node* IntrinsicsGenerator::ToString(Node* input, Node* arg_count, |
| 258 Node* context) { |
| 251 return IntrinsicAsStubCall(input, context, CodeFactory::ToString(isolate())); | 259 return IntrinsicAsStubCall(input, context, CodeFactory::ToString(isolate())); |
| 252 } | 260 } |
| 253 | 261 |
| 254 Node* IntrinsicsHelper::ToLength(Node* input, Node* arg_count, Node* context) { | 262 Node* IntrinsicsGenerator::ToLength(Node* input, Node* arg_count, |
| 263 Node* context) { |
| 255 return IntrinsicAsStubCall(input, context, CodeFactory::ToLength(isolate())); | 264 return IntrinsicAsStubCall(input, context, CodeFactory::ToLength(isolate())); |
| 256 } | 265 } |
| 257 | 266 |
| 258 Node* IntrinsicsHelper::ToInteger(Node* input, Node* arg_count, Node* context) { | 267 Node* IntrinsicsGenerator::ToInteger(Node* input, Node* arg_count, |
| 268 Node* context) { |
| 259 return IntrinsicAsStubCall(input, context, CodeFactory::ToInteger(isolate())); | 269 return IntrinsicAsStubCall(input, context, CodeFactory::ToInteger(isolate())); |
| 260 } | 270 } |
| 261 | 271 |
| 262 Node* IntrinsicsHelper::ToNumber(Node* input, Node* arg_count, Node* context) { | 272 Node* IntrinsicsGenerator::ToNumber(Node* input, Node* arg_count, |
| 273 Node* context) { |
| 263 return IntrinsicAsStubCall(input, context, CodeFactory::ToNumber(isolate())); | 274 return IntrinsicAsStubCall(input, context, CodeFactory::ToNumber(isolate())); |
| 264 } | 275 } |
| 265 | 276 |
| 266 Node* IntrinsicsHelper::ToObject(Node* input, Node* arg_count, Node* context) { | 277 Node* IntrinsicsGenerator::ToObject(Node* input, Node* arg_count, |
| 278 Node* context) { |
| 267 return IntrinsicAsStubCall(input, context, CodeFactory::ToObject(isolate())); | 279 return IntrinsicAsStubCall(input, context, CodeFactory::ToObject(isolate())); |
| 268 } | 280 } |
| 269 | 281 |
| 270 Node* IntrinsicsHelper::Call(Node* args_reg, Node* arg_count, Node* context) { | 282 Node* IntrinsicsGenerator::Call(Node* args_reg, Node* arg_count, |
| 283 Node* context) { |
| 271 // First argument register contains the function target. | 284 // First argument register contains the function target. |
| 272 Node* function = __ LoadRegister(args_reg); | 285 Node* function = __ LoadRegister(args_reg); |
| 273 | 286 |
| 274 // Receiver is the second runtime call argument. | 287 // Receiver is the second runtime call argument. |
| 275 Node* receiver_reg = __ NextRegister(args_reg); | 288 Node* receiver_reg = __ NextRegister(args_reg); |
| 276 Node* receiver_arg = __ RegisterLocation(receiver_reg); | 289 Node* receiver_arg = __ RegisterLocation(receiver_reg); |
| 277 | 290 |
| 278 // Subtract function and receiver from arg count. | 291 // Subtract function and receiver from arg count. |
| 279 Node* function_and_receiver_count = __ Int32Constant(2); | 292 Node* function_and_receiver_count = __ Int32Constant(2); |
| 280 Node* target_args_count = __ Int32Sub(arg_count, function_and_receiver_count); | 293 Node* target_args_count = __ Int32Sub(arg_count, function_and_receiver_count); |
| 281 | 294 |
| 282 if (FLAG_debug_code) { | 295 if (FLAG_debug_code) { |
| 283 InterpreterAssembler::Label arg_count_positive(assembler_); | 296 InterpreterAssembler::Label arg_count_positive(assembler_); |
| 284 Node* comparison = __ Int32LessThan(target_args_count, __ Int32Constant(0)); | 297 Node* comparison = __ Int32LessThan(target_args_count, __ Int32Constant(0)); |
| 285 __ GotoIfNot(comparison, &arg_count_positive); | 298 __ GotoIfNot(comparison, &arg_count_positive); |
| 286 __ Abort(kWrongArgumentCountForInvokeIntrinsic); | 299 __ Abort(kWrongArgumentCountForInvokeIntrinsic); |
| 287 __ Goto(&arg_count_positive); | 300 __ Goto(&arg_count_positive); |
| 288 __ Bind(&arg_count_positive); | 301 __ Bind(&arg_count_positive); |
| 289 } | 302 } |
| 290 | 303 |
| 291 Node* result = __ CallJS(function, context, receiver_arg, target_args_count, | 304 Node* result = __ CallJS(function, context, receiver_arg, target_args_count, |
| 292 TailCallMode::kDisallow); | 305 TailCallMode::kDisallow); |
| 293 return result; | 306 return result; |
| 294 } | 307 } |
| 295 | 308 |
| 296 Node* IntrinsicsHelper::ClassOf(Node* args_reg, Node* arg_count, | 309 Node* IntrinsicsGenerator::ClassOf(Node* args_reg, Node* arg_count, |
| 297 Node* context) { | 310 Node* context) { |
| 298 Node* value = __ LoadRegister(args_reg); | 311 Node* value = __ LoadRegister(args_reg); |
| 299 return __ ClassOf(value); | 312 return __ ClassOf(value); |
| 300 } | 313 } |
| 301 | 314 |
| 302 Node* IntrinsicsHelper::CreateAsyncFromSyncIterator(Node* args_reg, | 315 Node* IntrinsicsGenerator::CreateAsyncFromSyncIterator(Node* args_reg, |
| 303 Node* arg_count, | 316 Node* arg_count, |
| 304 Node* context) { | 317 Node* context) { |
| 305 InterpreterAssembler::Label not_receiver( | 318 InterpreterAssembler::Label not_receiver( |
| 306 assembler_, InterpreterAssembler::Label::kDeferred); | 319 assembler_, InterpreterAssembler::Label::kDeferred); |
| 307 InterpreterAssembler::Label done(assembler_); | 320 InterpreterAssembler::Label done(assembler_); |
| 308 InterpreterAssembler::Variable return_value(assembler_, | 321 InterpreterAssembler::Variable return_value(assembler_, |
| 309 MachineRepresentation::kTagged); | 322 MachineRepresentation::kTagged); |
| 310 | 323 |
| 311 Node* sync_iterator = __ LoadRegister(args_reg); | 324 Node* sync_iterator = __ LoadRegister(args_reg); |
| 312 | 325 |
| 313 __ GotoIf(__ TaggedIsSmi(sync_iterator), ¬_receiver); | 326 __ GotoIf(__ TaggedIsSmi(sync_iterator), ¬_receiver); |
| 314 __ GotoIfNot(__ IsJSReceiver(sync_iterator), ¬_receiver); | 327 __ GotoIfNot(__ IsJSReceiver(sync_iterator), ¬_receiver); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 330 __ CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context)); | 343 __ CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context)); |
| 331 | 344 |
| 332 // Unreachable due to the Throw in runtime call. | 345 // Unreachable due to the Throw in runtime call. |
| 333 __ Goto(&done); | 346 __ Goto(&done); |
| 334 } | 347 } |
| 335 | 348 |
| 336 __ Bind(&done); | 349 __ Bind(&done); |
| 337 return return_value.value(); | 350 return return_value.value(); |
| 338 } | 351 } |
| 339 | 352 |
| 340 void IntrinsicsHelper::AbortIfArgCountMismatch(int expected, Node* actual) { | 353 void IntrinsicsGenerator::AbortIfArgCountMismatch(int expected, Node* actual) { |
| 341 InterpreterAssembler::Label match(assembler_); | 354 InterpreterAssembler::Label match(assembler_); |
| 342 Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected)); | 355 Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected)); |
| 343 __ GotoIf(comparison, &match); | 356 __ GotoIf(comparison, &match); |
| 344 __ Abort(kWrongArgumentCountForInvokeIntrinsic); | 357 __ Abort(kWrongArgumentCountForInvokeIntrinsic); |
| 345 __ Goto(&match); | 358 __ Goto(&match); |
| 346 __ Bind(&match); | 359 __ Bind(&match); |
| 347 } | 360 } |
| 348 | 361 |
| 349 } // namespace interpreter | 362 } // namespace interpreter |
| 350 } // namespace internal | 363 } // namespace internal |
| 351 } // namespace v8 | 364 } // namespace v8 |
| OLD | NEW |