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