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 3 // found in the LICENSE file. 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/heap/factory-inl.h" 12 #include "src/interpreter/bytecodes.h" 13 #include "src/interpreter/interpreter-assembler.h" 14 #include "src/interpreter/interpreter-intrinsics.h" 15 #include "src/objects-inl.h" 16 #include "src/objects/js-generator.h" 17 #include "src/objects/module.h" 18 19 namespace v8 { 20 namespace internal { 21 namespace interpreter { 22 23 using compiler::Node; 24 template <typename T> 25 using TNode = compiler::TNode<T>; 26 27 class IntrinsicsGenerator { 28 public: 29 explicit IntrinsicsGenerator(InterpreterAssembler* assembler) 30 : isolate_(assembler->isolate()), 31 zone_(assembler->zone()), 32 assembler_(assembler) {} 33 34 Node* InvokeIntrinsic(Node* function_id, Node* context, 35 const InterpreterAssembler::RegListNodePair& args); 36 37 private: 38 enum InstanceTypeCompareMode { 39 kInstanceTypeEqual, 40 kInstanceTypeGreaterThanOrEqual 41 }; 42 43 Node* IsInstanceType(Node* input, int type); 44 Node* CompareInstanceType(Node* map, int type, InstanceTypeCompareMode mode); 45 Node* IntrinsicAsStubCall(const InterpreterAssembler::RegListNodePair& args, 46 Node* context, Callable const& callable); 47 Node* IntrinsicAsBuiltinCall( 48 const InterpreterAssembler::RegListNodePair& args, Node* context, 49 Builtins::Name name); 50 void AbortIfArgCountMismatch(int expected, compiler::Node* actual); 51 52 #define DECLARE_INTRINSIC_HELPER(name, lower_case, count) \ 53 Node* name(const InterpreterAssembler::RegListNodePair& args, Node* context); 54 INTRINSICS_LIST(DECLARE_INTRINSIC_HELPER) 55 #undef DECLARE_INTRINSIC_HELPER 56 57 Isolate* isolate() { return isolate_; } 58 Zone* zone() { return zone_; } 59 Factory* factory() { return isolate()->factory(); } 60 61 Isolate* isolate_; 62 Zone* zone_; 63 InterpreterAssembler* assembler_; 64 65 DISALLOW_COPY_AND_ASSIGN(IntrinsicsGenerator); 66 }; 67 68 Node* GenerateInvokeIntrinsic( 69 InterpreterAssembler* assembler, Node* function_id, Node* context, 70 const InterpreterAssembler::RegListNodePair& args) { 71 IntrinsicsGenerator generator(assembler); 72 return generator.InvokeIntrinsic(function_id, context, args); 73 } 74 75 #define __ assembler_-> 76 77 Node* IntrinsicsGenerator::InvokeIntrinsic( 78 Node* function_id, Node* context, 79 const InterpreterAssembler::RegListNodePair& args) { 80 InterpreterAssembler::Label abort(assembler_), end(assembler_); 81 InterpreterAssembler::Variable result(assembler_, 82 MachineRepresentation::kTagged); 83 84 #define MAKE_LABEL(name, lower_case, count) \ 85 InterpreterAssembler::Label lower_case(assembler_); 86 INTRINSICS_LIST(MAKE_LABEL) 87 #undef MAKE_LABEL 88 89 #define LABEL_POINTER(name, lower_case, count) &lower_case, 90 InterpreterAssembler::Label* labels[] = {INTRINSICS_LIST(LABEL_POINTER)}; 91 #undef LABEL_POINTER 92 93 #define CASE(name, lower_case, count) \ 94 static_cast<int32_t>(IntrinsicsHelper::IntrinsicId::k##name), 95 int32_t cases[] = {INTRINSICS_LIST(CASE)}; 96 #undef CASE 97 98 __ Switch(function_id, &abort, cases, labels, arraysize(cases)); 99 #define HANDLE_CASE(name, lower_case, expected_arg_count) \ 100 __ BIND(&lower_case); \ 101 { \ 102 if (FLAG_debug_code && expected_arg_count >= 0) { \ 103 AbortIfArgCountMismatch(expected_arg_count, args.reg_count()); \ 104 } \ 105 Node* value = name(args, context); \ 106 if (value) { \ 107 result.Bind(value); \ 108 __ Goto(&end); \ 109 } \ 110 } 111 INTRINSICS_LIST(HANDLE_CASE) 112 #undef HANDLE_CASE 113 114 __ BIND(&abort); 115 { 116 __ Abort(AbortReason::kUnexpectedFunctionIDForInvokeIntrinsic); 117 result.Bind(__ UndefinedConstant()); 118 __ Goto(&end); 119 } 120 121 __ BIND(&end); 122 return result.value(); 123 } 124 125 Node* IntrinsicsGenerator::CompareInstanceType(Node* object, int type, 126 InstanceTypeCompareMode mode) { 127 Node* instance_type = __ LoadInstanceType(object); 128 129 if (mode == kInstanceTypeEqual) { 130 return __ Word32Equal(instance_type, __ Int32Constant(type)); 131 } else { 132 DCHECK_EQ(mode, kInstanceTypeGreaterThanOrEqual); 133 return __ Int32GreaterThanOrEqual(instance_type, __ Int32Constant(type)); 134 } 135 } 136 137 Node* IntrinsicsGenerator::IsInstanceType(Node* input, int type) { 138 TNode<Oddball> result = __ Select<Oddball>( 139 __ TaggedIsSmi(input), [=] { return __ FalseConstant(); }, 140 [=] { 141 return __ SelectBooleanConstant( 142 CompareInstanceType(input, type, kInstanceTypeEqual)); 143 }); 144 return result; 145 } 146 147 Node* IntrinsicsGenerator::IsJSReceiver( 148 const InterpreterAssembler::RegListNodePair& args, Node* context) { 149 Node* input = __ LoadRegisterFromRegisterList(args, 0); 150 TNode<Oddball> result = __ Select<Oddball>( 151 __ TaggedIsSmi(input), [=] { return __ FalseConstant(); }, 152 [=] { return __ SelectBooleanConstant(__ IsJSReceiver(input)); }); 153 return result; 154 } 155 156 Node* IntrinsicsGenerator::IsArray( 157 const InterpreterAssembler::RegListNodePair& args, Node* context) { 158 Node* input = __ LoadRegisterFromRegisterList(args, 0); 159 return IsInstanceType(input, JS_ARRAY_TYPE); 160 } 161 162 Node* IntrinsicsGenerator::IsJSProxy( 163 const InterpreterAssembler::RegListNodePair& args, Node* context) { 164 Node* input = __ LoadRegisterFromRegisterList(args, 0); 165 return IsInstanceType(input, JS_PROXY_TYPE); 166 } 167 168 Node* IntrinsicsGenerator::IsTypedArray( 169 const InterpreterAssembler::RegListNodePair& args, Node* context) { 170 Node* input = __ LoadRegisterFromRegisterList(args, 0); 171 return IsInstanceType(input, JS_TYPED_ARRAY_TYPE); 172 } 173 174 Node* IntrinsicsGenerator::IsSmi( 175 const InterpreterAssembler::RegListNodePair& args, Node* context) { 176 Node* input = __ LoadRegisterFromRegisterList(args, 0); 177 return __ SelectBooleanConstant(__ TaggedIsSmi(input)); 178 } 179 180 Node* IntrinsicsGenerator::IntrinsicAsStubCall( 181 const InterpreterAssembler::RegListNodePair& args, Node* context, 182 Callable const& callable) { 183 int param_count = callable.descriptor().GetParameterCount(); 184 int input_count = param_count + 2; // +2 for target and context 185 Node** stub_args = zone()->NewArray<Node*>(input_count); 186 int index = 0; 187 stub_args[index++] = __ HeapConstant(callable.code()); 188 for (int i = 0; i < param_count; i++) { 189 stub_args[index++] = __ LoadRegisterFromRegisterList(args, i); 190 } 191 stub_args[index++] = context; 192 return __ CallStubN(callable.descriptor(), 1, input_count, stub_args); 193 } 194 195 Node* IntrinsicsGenerator::IntrinsicAsBuiltinCall( 196 const InterpreterAssembler::RegListNodePair& args, Node* context, 197 Builtins::Name name) { 198 Callable callable = Builtins::CallableFor(isolate_, name); 199 return IntrinsicAsStubCall(args, context, callable); 200 } 201 202 Node* IntrinsicsGenerator::CreateIterResultObject( 203 const InterpreterAssembler::RegListNodePair& args, Node* context) { 204 return IntrinsicAsStubCall( 205 args, context, 206 Builtins::CallableFor(isolate(), Builtins::kCreateIterResultObject)); 207 } 208 209 Node* IntrinsicsGenerator::HasProperty( 210 const InterpreterAssembler::RegListNodePair& args, Node* context) { 211 return IntrinsicAsStubCall( 212 args, context, Builtins::CallableFor(isolate(), Builtins::kHasProperty)); 213 } 214 215 Node* IntrinsicsGenerator::GetProperty( 216 const InterpreterAssembler::RegListNodePair& args, Node* context) { 217 return IntrinsicAsStubCall( 218 args, context, Builtins::CallableFor(isolate(), Builtins::kGetProperty)); 219 } 220 221 Node* IntrinsicsGenerator::RejectPromise( 222 const InterpreterAssembler::RegListNodePair& args, Node* context) { 223 return IntrinsicAsStubCall( 224 args, context, 225 Builtins::CallableFor(isolate(), Builtins::kRejectPromise)); 226 } 227 228 Node* IntrinsicsGenerator::ResolvePromise( 229 const InterpreterAssembler::RegListNodePair& args, Node* context) { 230 return IntrinsicAsStubCall( 231 args, context, 232 Builtins::CallableFor(isolate(), Builtins::kResolvePromise)); 233 } 234 235 Node* IntrinsicsGenerator::ToString( 236 const InterpreterAssembler::RegListNodePair& args, Node* context) { 237 return IntrinsicAsStubCall( 238 args, context, Builtins::CallableFor(isolate(), Builtins::kToString)); 239 } 240 241 Node* IntrinsicsGenerator::ToLength( 242 const InterpreterAssembler::RegListNodePair& args, Node* context) { 243 return IntrinsicAsStubCall( 244 args, context, Builtins::CallableFor(isolate(), Builtins::kToLength)); 245 } 246 247 Node* IntrinsicsGenerator::ToInteger( 248 const InterpreterAssembler::RegListNodePair& args, Node* context) { 249 return IntrinsicAsStubCall( 250 args, context, Builtins::CallableFor(isolate(), Builtins::kToInteger)); 251 } 252 253 Node* IntrinsicsGenerator::ToNumber( 254 const InterpreterAssembler::RegListNodePair& args, Node* context) { 255 return IntrinsicAsStubCall( 256 args, context, Builtins::CallableFor(isolate(), Builtins::kToNumber)); 257 } 258 259 Node* IntrinsicsGenerator::ToObject( 260 const InterpreterAssembler::RegListNodePair& args, Node* context) { 261 return IntrinsicAsStubCall( 262 args, context, Builtins::CallableFor(isolate(), Builtins::kToObject)); 263 } 264 265 Node* IntrinsicsGenerator::Call( 266 const InterpreterAssembler::RegListNodePair& args, Node* context) { 267 // First argument register contains the function target. 268 Node* function = __ LoadRegisterFromRegisterList(args, 0); 269 270 // The arguments for the target function are from the second runtime call 271 // argument. 272 InterpreterAssembler::RegListNodePair target_args( 273 __ RegisterLocationInRegisterList(args, 1), 274 __ Int32Sub(args.reg_count(), __ Int32Constant(1))); 275 276 if (FLAG_debug_code) { 277 InterpreterAssembler::Label arg_count_positive(assembler_); 278 Node* comparison = 279 __ Int32LessThan(target_args.reg_count(), __ Int32Constant(0)); 280 __ GotoIfNot(comparison, &arg_count_positive); 281 __ Abort(AbortReason::kWrongArgumentCountForInvokeIntrinsic); 282 __ Goto(&arg_count_positive); 283 __ BIND(&arg_count_positive); 284 } 285 286 __ CallJSAndDispatch(function, context, target_args, 287 ConvertReceiverMode::kAny); 288 return nullptr; // We never return from the CallJSAndDispatch above. 289 } 290 291 Node* IntrinsicsGenerator::CreateAsyncFromSyncIterator( 292 const InterpreterAssembler::RegListNodePair& args, Node* context) { 293 InterpreterAssembler::Label not_receiver( 294 assembler_, InterpreterAssembler::Label::kDeferred); 295 InterpreterAssembler::Label done(assembler_); 296 InterpreterAssembler::Variable return_value(assembler_, 297 MachineRepresentation::kTagged); 298 299 Node* sync_iterator = __ LoadRegisterFromRegisterList(args, 0); 300 301 __ GotoIf(__ TaggedIsSmi(sync_iterator), ¬_receiver); 302 __ GotoIfNot(__ IsJSReceiver(sync_iterator), ¬_receiver); 303 304 Node* const next = 305 __ GetProperty(context, sync_iterator, factory()->next_string()); 306 307 Node* const native_context = __ LoadNativeContext(context); 308 Node* const map = __ LoadContextElement( 309 native_context, Context::ASYNC_FROM_SYNC_ITERATOR_MAP_INDEX); 310 Node* const iterator = __ AllocateJSObjectFromMap(map); 311 312 __ StoreObjectFieldNoWriteBarrier( 313 iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset, sync_iterator); 314 __ StoreObjectFieldNoWriteBarrier(iterator, 315 JSAsyncFromSyncIterator::kNextOffset, next); 316 317 return_value.Bind(iterator); 318 __ Goto(&done); 319 320 __ BIND(¬_receiver); 321 { 322 return_value.Bind( 323 __ CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context)); 324 325 // Unreachable due to the Throw in runtime call. 326 __ Goto(&done); 327 } 328 329 __ BIND(&done); 330 return return_value.value(); 331 } 332 333 Node* IntrinsicsGenerator::CreateJSGeneratorObject( 334 const InterpreterAssembler::RegListNodePair& args, Node* context) { 335 return IntrinsicAsBuiltinCall(args, context, 336 Builtins::kCreateGeneratorObject); 337 } 338 339 Node* IntrinsicsGenerator::GeneratorGetInputOrDebugPos( 340 const InterpreterAssembler::RegListNodePair& args, Node* context) { 341 Node* generator = __ LoadRegisterFromRegisterList(args, 0); 342 Node* const value = 343 __ LoadObjectField(generator, JSGeneratorObject::kInputOrDebugPosOffset); 344 345 return value; 346 } 347 348 Node* IntrinsicsGenerator::GeneratorGetResumeMode( 349 const InterpreterAssembler::RegListNodePair& args, Node* context) { 350 Node* generator = __ LoadRegisterFromRegisterList(args, 0); 351 Node* const value = 352 __ LoadObjectField(generator, JSGeneratorObject::kResumeModeOffset); 353 354 return value; 355 } 356 357 Node* IntrinsicsGenerator::GeneratorClose( 358 const InterpreterAssembler::RegListNodePair& args, Node* context) { 359 Node* generator = __ LoadRegisterFromRegisterList(args, 0); 360 __ StoreObjectFieldNoWriteBarrier( 361 generator, JSGeneratorObject::kContinuationOffset, 362 __ SmiConstant(JSGeneratorObject::kGeneratorClosed)); 363 return __ UndefinedConstant(); 364 } 365 366 Node* IntrinsicsGenerator::GetImportMetaObject( 367 const InterpreterAssembler::RegListNodePair& args, Node* context) { 368 Node* const module_context = __ LoadModuleContext(context); 369 Node* const module = 370 __ LoadContextElement(module_context, Context::EXTENSION_INDEX); 371 Node* const import_meta = 372 __ LoadObjectField(module, Module::kImportMetaOffset); 373 374 InterpreterAssembler::Variable return_value(assembler_, 375 MachineRepresentation::kTagged); 376 return_value.Bind(import_meta); 377 378 InterpreterAssembler::Label end(assembler_); 379 __ GotoIfNot(__ IsTheHole(import_meta), &end); 380 381 return_value.Bind(__ CallRuntime(Runtime::kGetImportMetaObject, context)); 382 __ Goto(&end); 383 384 __ BIND(&end); 385 return return_value.value(); 386 } 387 388 Node* IntrinsicsGenerator::AsyncGeneratorReject( 389 const InterpreterAssembler::RegListNodePair& args, Node* context) { 390 return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncGeneratorReject); 391 } 392 393 Node* IntrinsicsGenerator::AsyncGeneratorResolve( 394 const InterpreterAssembler::RegListNodePair& args, Node* context) { 395 return IntrinsicAsBuiltinCall(args, context, 396 Builtins::kAsyncGeneratorResolve); 397 } 398 399 Node* IntrinsicsGenerator::AsyncGeneratorYield( 400 const InterpreterAssembler::RegListNodePair& args, Node* context) { 401 return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncGeneratorYield); 402 } 403 404 void IntrinsicsGenerator::AbortIfArgCountMismatch(int expected, Node* actual) { 405 InterpreterAssembler::Label match(assembler_); 406 Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected)); 407 __ GotoIf(comparison, &match); 408 __ Abort(AbortReason::kWrongArgumentCountForInvokeIntrinsic); 409 __ Goto(&match); 410 __ BIND(&match); 411 } 412 413 #undef __ 414 415 } // namespace interpreter 416 } // namespace internal 417 } // namespace v8 418