| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 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.h" | 5 #include "src/interpreter/interpreter-intrinsics.h" |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 | 74 |
| 75 #define LABEL_POINTER(name, lower_case, count) &lower_case, | 75 #define LABEL_POINTER(name, lower_case, count) &lower_case, |
| 76 InterpreterAssembler::Label* labels[] = {INTRINSICS_LIST(LABEL_POINTER)}; | 76 InterpreterAssembler::Label* labels[] = {INTRINSICS_LIST(LABEL_POINTER)}; |
| 77 #undef LABEL_POINTER | 77 #undef LABEL_POINTER |
| 78 | 78 |
| 79 #define CASE(name, lower_case, count) \ | 79 #define CASE(name, lower_case, count) \ |
| 80 static_cast<int32_t>(IntrinsicId::k##name), | 80 static_cast<int32_t>(IntrinsicId::k##name), |
| 81 int32_t cases[] = {INTRINSICS_LIST(CASE)}; | 81 int32_t cases[] = {INTRINSICS_LIST(CASE)}; |
| 82 #undef CASE | 82 #undef CASE |
| 83 | 83 |
| 84 __ Switch(function_id, &abort, cases, labels, arraysize(cases)); | 84 __ Switch(__ TruncateWordToWord32(function_id), &abort, cases, labels, |
| 85 arraysize(cases)); |
| 85 #define HANDLE_CASE(name, lower_case, expected_arg_count) \ | 86 #define HANDLE_CASE(name, lower_case, expected_arg_count) \ |
| 86 __ Bind(&lower_case); \ | 87 __ Bind(&lower_case); \ |
| 87 if (FLAG_debug_code && expected_arg_count >= 0) { \ | 88 if (FLAG_debug_code && expected_arg_count >= 0) { \ |
| 88 AbortIfArgCountMismatch(expected_arg_count, arg_count); \ | 89 AbortIfArgCountMismatch(expected_arg_count, arg_count); \ |
| 89 } \ | 90 } \ |
| 90 result.Bind(name(first_arg_reg, arg_count, context)); \ | 91 result.Bind(name(first_arg_reg, arg_count, context)); \ |
| 91 __ Goto(&end); | 92 __ Goto(&end); |
| 92 INTRINSICS_LIST(HANDLE_CASE) | 93 INTRINSICS_LIST(HANDLE_CASE) |
| 93 #undef HANDLE_CASE | 94 #undef HANDLE_CASE |
| 94 | 95 |
| 95 __ Bind(&abort); | 96 __ Bind(&abort); |
| 96 { | 97 { |
| 97 __ Abort(BailoutReason::kUnexpectedFunctionIDForInvokeIntrinsic); | 98 __ Abort(BailoutReason::kUnexpectedFunctionIDForInvokeIntrinsic); |
| 98 result.Bind(__ UndefinedConstant()); | 99 result.Bind(__ UndefinedConstant()); |
| 99 __ Goto(&end); | 100 __ Goto(&end); |
| 100 } | 101 } |
| 101 | 102 |
| 102 __ Bind(&end); | 103 __ Bind(&end); |
| 103 return result.value(); | 104 return result.value(); |
| 104 } | 105 } |
| 105 | 106 |
| 106 Node* IntrinsicsHelper::CompareInstanceType(Node* object, int type, | 107 Node* IntrinsicsHelper::CompareInstanceType(Node* object, int type, |
| 107 InstanceTypeCompareMode mode) { | 108 InstanceTypeCompareMode mode) { |
| 108 InterpreterAssembler::Variable return_value(assembler_, | |
| 109 MachineRepresentation::kTagged); | |
| 110 Node* instance_type = __ LoadInstanceType(object); | 109 Node* instance_type = __ LoadInstanceType(object); |
| 111 | 110 |
| 112 InterpreterAssembler::Label if_true(assembler_), if_false(assembler_), | |
| 113 end(assembler_); | |
| 114 if (mode == kInstanceTypeEqual) { | 111 if (mode == kInstanceTypeEqual) { |
| 115 return __ Word32Equal(instance_type, __ Int32Constant(type)); | 112 return __ Word32Equal(instance_type, __ Int32Constant(type)); |
| 116 } else { | 113 } else { |
| 117 DCHECK(mode == kInstanceTypeGreaterThanOrEqual); | 114 DCHECK(mode == kInstanceTypeGreaterThanOrEqual); |
| 118 return __ Int32GreaterThanOrEqual(instance_type, __ Int32Constant(type)); | 115 return __ Int32GreaterThanOrEqual(instance_type, __ Int32Constant(type)); |
| 119 } | 116 } |
| 120 } | 117 } |
| 121 | 118 |
| 122 Node* IntrinsicsHelper::IsInstanceType(Node* input, int type) { | 119 Node* IntrinsicsHelper::IsInstanceType(Node* input, int type) { |
| 123 InterpreterAssembler::Variable return_value(assembler_, | 120 InterpreterAssembler::Variable return_value(assembler_, |
| 124 MachineRepresentation::kTagged); | 121 MachineRepresentation::kTagged); |
| 122 // TODO(ishell): Use Select here. |
| 125 InterpreterAssembler::Label if_not_smi(assembler_), return_true(assembler_), | 123 InterpreterAssembler::Label if_not_smi(assembler_), return_true(assembler_), |
| 126 return_false(assembler_), end(assembler_); | 124 return_false(assembler_), end(assembler_); |
| 127 Node* arg = __ LoadRegister(input); | 125 Node* arg = __ LoadRegister(input); |
| 128 __ GotoIf(__ TaggedIsSmi(arg), &return_false); | 126 __ GotoIf(__ TaggedIsSmi(arg), &return_false); |
| 129 | 127 |
| 130 Node* condition = CompareInstanceType(arg, type, kInstanceTypeEqual); | 128 Node* condition = CompareInstanceType(arg, type, kInstanceTypeEqual); |
| 131 __ Branch(condition, &return_true, &return_false); | 129 __ Branch(condition, &return_true, &return_false); |
| 132 | 130 |
| 133 __ Bind(&return_true); | 131 __ Bind(&return_true); |
| 134 { | 132 { |
| 135 return_value.Bind(__ BooleanConstant(true)); | 133 return_value.Bind(__ BooleanConstant(true)); |
| 136 __ Goto(&end); | 134 __ Goto(&end); |
| 137 } | 135 } |
| 138 | 136 |
| 139 __ Bind(&return_false); | 137 __ Bind(&return_false); |
| 140 { | 138 { |
| 141 return_value.Bind(__ BooleanConstant(false)); | 139 return_value.Bind(__ BooleanConstant(false)); |
| 142 __ Goto(&end); | 140 __ Goto(&end); |
| 143 } | 141 } |
| 144 | 142 |
| 145 __ Bind(&end); | 143 __ Bind(&end); |
| 146 return return_value.value(); | 144 return return_value.value(); |
| 147 } | 145 } |
| 148 | 146 |
| 149 Node* IntrinsicsHelper::IsJSReceiver(Node* input, Node* arg_count, | 147 Node* IntrinsicsHelper::IsJSReceiver(Node* input, Node* arg_count, |
| 150 Node* context) { | 148 Node* context) { |
| 149 // TODO(ishell): Use Select here. |
| 150 // TODO(ishell): Use CSA::IsJSReceiverInstanceType here. |
| 151 InterpreterAssembler::Variable return_value(assembler_, | 151 InterpreterAssembler::Variable return_value(assembler_, |
| 152 MachineRepresentation::kTagged); | 152 MachineRepresentation::kTagged); |
| 153 InterpreterAssembler::Label return_true(assembler_), return_false(assembler_), | 153 InterpreterAssembler::Label return_true(assembler_), return_false(assembler_), |
| 154 end(assembler_); | 154 end(assembler_); |
| 155 | 155 |
| 156 Node* arg = __ LoadRegister(input); | 156 Node* arg = __ LoadRegister(input); |
| 157 __ GotoIf(__ TaggedIsSmi(arg), &return_false); | 157 __ GotoIf(__ TaggedIsSmi(arg), &return_false); |
| 158 | 158 |
| 159 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); | 159 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); |
| 160 Node* condition = CompareInstanceType(arg, FIRST_JS_RECEIVER_TYPE, | 160 Node* condition = CompareInstanceType(arg, FIRST_JS_RECEIVER_TYPE, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 188 Node* IntrinsicsHelper::IsRegExp(Node* input, Node* arg_count, Node* context) { | 188 Node* IntrinsicsHelper::IsRegExp(Node* input, Node* arg_count, Node* context) { |
| 189 return IsInstanceType(input, JS_REGEXP_TYPE); | 189 return IsInstanceType(input, JS_REGEXP_TYPE); |
| 190 } | 190 } |
| 191 | 191 |
| 192 Node* IntrinsicsHelper::IsTypedArray(Node* input, Node* arg_count, | 192 Node* IntrinsicsHelper::IsTypedArray(Node* input, Node* arg_count, |
| 193 Node* context) { | 193 Node* context) { |
| 194 return IsInstanceType(input, JS_TYPED_ARRAY_TYPE); | 194 return IsInstanceType(input, JS_TYPED_ARRAY_TYPE); |
| 195 } | 195 } |
| 196 | 196 |
| 197 Node* IntrinsicsHelper::IsSmi(Node* input, Node* arg_count, Node* context) { | 197 Node* IntrinsicsHelper::IsSmi(Node* input, Node* arg_count, Node* context) { |
| 198 // TODO(ishell): Use SelectBooleanConstant here. |
| 198 InterpreterAssembler::Variable return_value(assembler_, | 199 InterpreterAssembler::Variable return_value(assembler_, |
| 199 MachineRepresentation::kTagged); | 200 MachineRepresentation::kTagged); |
| 200 InterpreterAssembler::Label if_smi(assembler_), if_not_smi(assembler_), | 201 InterpreterAssembler::Label if_smi(assembler_), if_not_smi(assembler_), |
| 201 end(assembler_); | 202 end(assembler_); |
| 202 | 203 |
| 203 Node* arg = __ LoadRegister(input); | 204 Node* arg = __ LoadRegister(input); |
| 204 | 205 |
| 205 __ Branch(__ TaggedIsSmi(arg), &if_smi, &if_not_smi); | 206 __ Branch(__ TaggedIsSmi(arg), &if_smi, &if_not_smi); |
| 206 __ Bind(&if_smi); | 207 __ Bind(&if_smi); |
| 207 { | 208 { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 | 282 |
| 282 Node* IntrinsicsHelper::Call(Node* args_reg, Node* arg_count, Node* context) { | 283 Node* IntrinsicsHelper::Call(Node* args_reg, Node* arg_count, Node* context) { |
| 283 // First argument register contains the function target. | 284 // First argument register contains the function target. |
| 284 Node* function = __ LoadRegister(args_reg); | 285 Node* function = __ LoadRegister(args_reg); |
| 285 | 286 |
| 286 // Receiver is the second runtime call argument. | 287 // Receiver is the second runtime call argument. |
| 287 Node* receiver_reg = __ NextRegister(args_reg); | 288 Node* receiver_reg = __ NextRegister(args_reg); |
| 288 Node* receiver_arg = __ RegisterLocation(receiver_reg); | 289 Node* receiver_arg = __ RegisterLocation(receiver_reg); |
| 289 | 290 |
| 290 // Subtract function and receiver from arg count. | 291 // Subtract function and receiver from arg count. |
| 291 Node* function_and_receiver_count = __ Int32Constant(2); | 292 Node* function_and_receiver_count = __ IntPtrConstant(2); |
| 292 Node* target_args_count = __ Int32Sub(arg_count, function_and_receiver_count); | 293 Node* target_args_count = |
| 294 __ IntPtrSub(arg_count, function_and_receiver_count); |
| 293 | 295 |
| 294 if (FLAG_debug_code) { | 296 if (FLAG_debug_code) { |
| 295 InterpreterAssembler::Label arg_count_positive(assembler_); | 297 InterpreterAssembler::Label arg_count_positive(assembler_); |
| 296 Node* comparison = __ Int32LessThan(target_args_count, __ Int32Constant(0)); | 298 Node* comparison = |
| 299 __ IntPtrLessThan(target_args_count, __ IntPtrConstant(0)); |
| 297 __ GotoUnless(comparison, &arg_count_positive); | 300 __ GotoUnless(comparison, &arg_count_positive); |
| 298 __ Abort(kWrongArgumentCountForInvokeIntrinsic); | 301 __ Abort(kWrongArgumentCountForInvokeIntrinsic); |
| 299 __ Goto(&arg_count_positive); | 302 __ Goto(&arg_count_positive); |
| 300 __ Bind(&arg_count_positive); | 303 __ Bind(&arg_count_positive); |
| 301 } | 304 } |
| 302 | 305 |
| 303 Node* result = __ CallJS(function, context, receiver_arg, target_args_count, | 306 Node* result = __ CallJS(function, context, receiver_arg, target_args_count, |
| 304 TailCallMode::kDisallow); | 307 TailCallMode::kDisallow); |
| 305 return result; | 308 return result; |
| 306 } | 309 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 return_value.Bind(__ LoadRoot(Heap::kObject_stringRootIndex)); | 388 return_value.Bind(__ LoadRoot(Heap::kObject_stringRootIndex)); |
| 386 __ Goto(&done); | 389 __ Goto(&done); |
| 387 } | 390 } |
| 388 | 391 |
| 389 __ Bind(&done); | 392 __ Bind(&done); |
| 390 return return_value.value(); | 393 return return_value.value(); |
| 391 } | 394 } |
| 392 | 395 |
| 393 void IntrinsicsHelper::AbortIfArgCountMismatch(int expected, Node* actual) { | 396 void IntrinsicsHelper::AbortIfArgCountMismatch(int expected, Node* actual) { |
| 394 InterpreterAssembler::Label match(assembler_); | 397 InterpreterAssembler::Label match(assembler_); |
| 395 Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected)); | 398 Node* comparison = __ WordEqual(actual, __ IntPtrConstant(expected)); |
| 396 __ GotoIf(comparison, &match); | 399 __ GotoIf(comparison, &match); |
| 397 __ Abort(kWrongArgumentCountForInvokeIntrinsic); | 400 __ Abort(kWrongArgumentCountForInvokeIntrinsic); |
| 398 __ Goto(&match); | 401 __ Goto(&match); |
| 399 __ Bind(&match); | 402 __ Bind(&match); |
| 400 } | 403 } |
| 401 | 404 |
| 402 } // namespace interpreter | 405 } // namespace interpreter |
| 403 } // namespace internal | 406 } // namespace internal |
| 404 } // namespace v8 | 407 } // namespace v8 |
| OLD | NEW |