1 // Copyright 2014 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/runtime/runtime-utils.h" 6 7 #include <memory> 8 9 #include "src/arguments.h" 10 #include "src/ast/prettyprinter.h" 11 #include "src/bootstrapper.h" 12 #include "src/conversions.h" 13 #include "src/debug/debug.h" 14 #include "src/frames-inl.h" 15 #include "src/isolate-inl.h" 16 #include "src/messages.h" 17 #include "src/parsing/parse-info.h" 18 #include "src/parsing/parser.h" 19 #include "src/wasm/wasm-module.h" 20 21 namespace v8 { 22 namespace internal { 23 24 RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping) { 25 SealHandleScope shs(isolate); 26 DCHECK(args.length() == 0); 27 CHECK(isolate->bootstrapper()->IsActive()); 28 return isolate->heap()->undefined_value(); 29 } 30 31 32 RUNTIME_FUNCTION(Runtime_ExportFromRuntime) { 33 HandleScope scope(isolate); 34 DCHECK(args.length() == 1); 35 CONVERT_ARG_HANDLE_CHECKED(JSObject, container, 0); 36 CHECK(isolate->bootstrapper()->IsActive()); 37 JSObject::NormalizeProperties(container, KEEP_INOBJECT_PROPERTIES, 10, 38 "ExportFromRuntime"); 39 Bootstrapper::ExportFromRuntime(isolate, container); 40 JSObject::MigrateSlowToFast(container, 0, "ExportFromRuntime"); 41 return *container; 42 } 43 44 45 RUNTIME_FUNCTION(Runtime_ExportExperimentalFromRuntime) { 46 HandleScope scope(isolate); 47 DCHECK(args.length() == 1); 48 CONVERT_ARG_HANDLE_CHECKED(JSObject, container, 0); 49 CHECK(isolate->bootstrapper()->IsActive()); 50 JSObject::NormalizeProperties(container, KEEP_INOBJECT_PROPERTIES, 10, 51 "ExportExperimentalFromRuntime"); 52 Bootstrapper::ExportExperimentalFromRuntime(isolate, container); 53 JSObject::MigrateSlowToFast(container, 0, "ExportExperimentalFromRuntime"); 54 return *container; 55 } 56 57 58 RUNTIME_FUNCTION(Runtime_InstallToContext) { 59 HandleScope scope(isolate); 60 DCHECK(args.length() == 1); 61 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); 62 CHECK(array->HasFastElements()); 63 CHECK(isolate->bootstrapper()->IsActive()); 64 Handle<Context> native_context = isolate->native_context(); 65 Handle<FixedArray> fixed_array(FixedArray::cast(array->elements())); 66 int length = Smi::cast(array->length())->value(); 67 for (int i = 0; i < length; i += 2) { 68 CHECK(fixed_array->get(i)->IsString()); 69 Handle<String> name(String::cast(fixed_array->get(i))); 70 CHECK(fixed_array->get(i + 1)->IsJSObject()); 71 Handle<JSObject> object(JSObject::cast(fixed_array->get(i + 1))); 72 int index = Context::ImportedFieldIndexForName(name); 73 if (index == Context::kNotFound) { 74 index = Context::IntrinsicIndexForName(name); 75 } 76 CHECK(index != Context::kNotFound); 77 native_context->set(index, *object); 78 } 79 return isolate->heap()->undefined_value(); 80 } 81 82 83 RUNTIME_FUNCTION(Runtime_Throw) { 84 HandleScope scope(isolate); 85 DCHECK(args.length() == 1); 86 return isolate->Throw(args[0]); 87 } 88 89 90 RUNTIME_FUNCTION(Runtime_ReThrow) { 91 HandleScope scope(isolate); 92 DCHECK(args.length() == 1); 93 return isolate->ReThrow(args[0]); 94 } 95 96 97 RUNTIME_FUNCTION(Runtime_ThrowStackOverflow) { 98 SealHandleScope shs(isolate); 99 DCHECK_LE(0, args.length()); 100 return isolate->StackOverflow(); 101 } 102 103 RUNTIME_FUNCTION(Runtime_ThrowTypeError) { 104 HandleScope scope(isolate); 105 DCHECK_LE(1, args.length()); 106 CONVERT_SMI_ARG_CHECKED(message_id_smi, 0); 107 108 Handle<Object> undefined = isolate->factory()->undefined_value(); 109 Handle<Object> arg0 = (args.length() > 1) ? args.at<Object>(1) : undefined; 110 Handle<Object> arg1 = (args.length() > 2) ? args.at<Object>(2) : undefined; 111 Handle<Object> arg2 = (args.length() > 3) ? args.at<Object>(3) : undefined; 112 113 MessageTemplate::Template message_id = 114 static_cast<MessageTemplate::Template>(message_id_smi); 115 116 THROW_NEW_ERROR_RETURN_FAILURE(isolate, 117 NewTypeError(message_id, arg0, arg1, arg2)); 118 } 119 120 RUNTIME_FUNCTION(Runtime_ThrowWasmError) { 121 HandleScope scope(isolate); 122 DCHECK_EQ(2, args.length()); 123 CONVERT_SMI_ARG_CHECKED(message_id, 0); 124 CONVERT_SMI_ARG_CHECKED(byte_offset, 1); 125 Handle<Object> error_obj = isolate->factory()->NewWasmRuntimeError( 126 static_cast<MessageTemplate::Template>(message_id)); 127 128 // For wasm traps, the byte offset (a.k.a source position) can not be 129 // determined from relocation info, since the explicit checks for traps 130 // converge in one singe block which calls this runtime function. 131 // We hence pass the byte offset explicitely, and patch it into the top-most 132 // frame (a wasm frame) on the collected stack trace. 133 // TODO(wasm): This implementation is temporary, see bug #5007: 134 // https://bugs.chromium.org/p/v8/issues/detail?id=5007 135 Handle<JSObject> error = Handle<JSObject>::cast(error_obj); 136 Handle<Object> stack_trace_obj = JSReceiver::GetDataProperty( 137 error, isolate->factory()->stack_trace_symbol()); 138 // Patch the stack trace (array of <receiver, function, code, position>). 139 if (stack_trace_obj->IsJSArray()) { 140 Handle<FrameArray> stack_elements( 141 FrameArray::cast(JSArray::cast(*stack_trace_obj)->elements())); 142 DCHECK(stack_elements->Code(0)->kind() == AbstractCode::WASM_FUNCTION); 143 DCHECK(stack_elements->Offset(0)->value() >= 0); 144 stack_elements->SetOffset(0, Smi::FromInt(-1 - byte_offset)); 145 } 146 147 // Patch the detailed stack trace (array of JSObjects with various 148 // properties). 149 Handle<Object> detailed_stack_trace_obj = JSReceiver::GetDataProperty( 150 error, isolate->factory()->detailed_stack_trace_symbol()); 151 if (detailed_stack_trace_obj->IsJSArray()) { 152 Handle<FixedArray> stack_elements( 153 FixedArray::cast(JSArray::cast(*detailed_stack_trace_obj)->elements())); 154 DCHECK_GE(stack_elements->length(), 1); 155 Handle<JSObject> top_frame(JSObject::cast(stack_elements->get(0))); 156 Handle<String> wasm_offset_key = 157 isolate->factory()->InternalizeOneByteString( 158 STATIC_CHAR_VECTOR("column")); 159 LookupIterator it(top_frame, wasm_offset_key, top_frame, 160 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); 161 if (it.IsFound()) { 162 DCHECK(JSReceiver::GetDataProperty(&it)->IsSmi()); 163 // Make column number 1-based here. 164 Maybe<bool> data_set = JSReceiver::SetDataProperty( 165 &it, handle(Smi::FromInt(byte_offset + 1), isolate)); 166 DCHECK(data_set.IsJust() && data_set.FromJust() == true); 167 USE(data_set); 168 } 169 } 170 171 return isolate->Throw(*error_obj); 172 } 173 174 RUNTIME_FUNCTION(Runtime_UnwindAndFindExceptionHandler) { 175 SealHandleScope shs(isolate); 176 DCHECK(args.length() == 0); 177 return isolate->UnwindAndFindHandler(); 178 } 179 180 181 RUNTIME_FUNCTION(Runtime_PromoteScheduledException) { 182 SealHandleScope shs(isolate); 183 DCHECK(args.length() == 0); 184 return isolate->PromoteScheduledException(); 185 } 186 187 188 RUNTIME_FUNCTION(Runtime_ThrowReferenceError) { 189 HandleScope scope(isolate); 190 DCHECK(args.length() == 1); 191 CONVERT_ARG_HANDLE_CHECKED(Object, name, 0); 192 THROW_NEW_ERROR_RETURN_FAILURE( 193 isolate, NewReferenceError(MessageTemplate::kNotDefined, name)); 194 } 195 196 197 RUNTIME_FUNCTION(Runtime_NewTypeError) { 198 HandleScope scope(isolate); 199 DCHECK(args.length() == 2); 200 CONVERT_INT32_ARG_CHECKED(template_index, 0); 201 CONVERT_ARG_HANDLE_CHECKED(Object, arg0, 1); 202 auto message_template = 203 static_cast<MessageTemplate::Template>(template_index); 204 return *isolate->factory()->NewTypeError(message_template, arg0); 205 } 206 207 208 RUNTIME_FUNCTION(Runtime_NewReferenceError) { 209 HandleScope scope(isolate); 210 DCHECK(args.length() == 2); 211 CONVERT_INT32_ARG_CHECKED(template_index, 0); 212 CONVERT_ARG_HANDLE_CHECKED(Object, arg0, 1); 213 auto message_template = 214 static_cast<MessageTemplate::Template>(template_index); 215 return *isolate->factory()->NewReferenceError(message_template, arg0); 216 } 217 218 219 RUNTIME_FUNCTION(Runtime_NewSyntaxError) { 220 HandleScope scope(isolate); 221 DCHECK(args.length() == 2); 222 CONVERT_INT32_ARG_CHECKED(template_index, 0); 223 CONVERT_ARG_HANDLE_CHECKED(Object, arg0, 1); 224 auto message_template = 225 static_cast<MessageTemplate::Template>(template_index); 226 return *isolate->factory()->NewSyntaxError(message_template, arg0); 227 } 228 229 RUNTIME_FUNCTION(Runtime_ThrowCannotConvertToPrimitive) { 230 HandleScope scope(isolate); 231 THROW_NEW_ERROR_RETURN_FAILURE( 232 isolate, NewTypeError(MessageTemplate::kCannotConvertToPrimitive)); 233 } 234 235 RUNTIME_FUNCTION(Runtime_ThrowIllegalInvocation) { 236 HandleScope scope(isolate); 237 DCHECK(args.length() == 0); 238 THROW_NEW_ERROR_RETURN_FAILURE( 239 isolate, NewTypeError(MessageTemplate::kIllegalInvocation)); 240 } 241 242 RUNTIME_FUNCTION(Runtime_ThrowIncompatibleMethodReceiver) { 243 HandleScope scope(isolate); 244 DCHECK_EQ(2, args.length()); 245 CONVERT_ARG_HANDLE_CHECKED(Object, arg0, 0); 246 CONVERT_ARG_HANDLE_CHECKED(Object, arg1, 1); 247 THROW_NEW_ERROR_RETURN_FAILURE( 248 isolate, 249 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, arg0, arg1)); 250 } 251 252 RUNTIME_FUNCTION(Runtime_ThrowInvalidStringLength) { 253 HandleScope scope(isolate); 254 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError()); 255 } 256 257 RUNTIME_FUNCTION(Runtime_ThrowIteratorResultNotAnObject) { 258 HandleScope scope(isolate); 259 DCHECK(args.length() == 1); 260 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0); 261 THROW_NEW_ERROR_RETURN_FAILURE( 262 isolate, 263 NewTypeError(MessageTemplate::kIteratorResultNotAnObject, value)); 264 } 265 266 RUNTIME_FUNCTION(Runtime_ThrowNotGeneric) { 267 HandleScope scope(isolate); 268 DCHECK_EQ(1, args.length()); 269 CONVERT_ARG_HANDLE_CHECKED(Object, arg0, 0); 270 THROW_NEW_ERROR_RETURN_FAILURE( 271 isolate, NewTypeError(MessageTemplate::kNotGeneric, arg0)); 272 } 273 274 RUNTIME_FUNCTION(Runtime_ThrowGeneratorRunning) { 275 HandleScope scope(isolate); 276 DCHECK_EQ(0, args.length()); 277 THROW_NEW_ERROR_RETURN_FAILURE( 278 isolate, NewTypeError(MessageTemplate::kGeneratorRunning)); 279 } 280 281 RUNTIME_FUNCTION(Runtime_ThrowApplyNonFunction) { 282 HandleScope scope(isolate); 283 DCHECK_EQ(1, args.length()); 284 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 285 Handle<String> type = Object::TypeOf(isolate, object); 286 THROW_NEW_ERROR_RETURN_FAILURE( 287 isolate, NewTypeError(MessageTemplate::kApplyNonFunction, object, type)); 288 } 289 290 291 RUNTIME_FUNCTION(Runtime_StackGuard) { 292 SealHandleScope shs(isolate); 293 DCHECK(args.length() == 0); 294 295 // First check if this is a real stack overflow. 296 StackLimitCheck check(isolate); 297 if (check.JsHasOverflowed()) { 298 return isolate->StackOverflow(); 299 } 300 301 return isolate->stack_guard()->HandleInterrupts(); 302 } 303 304 305 RUNTIME_FUNCTION(Runtime_Interrupt) { 306 SealHandleScope shs(isolate); 307 DCHECK(args.length() == 0); 308 return isolate->stack_guard()->HandleInterrupts(); 309 } 310 311 312 RUNTIME_FUNCTION(Runtime_AllocateInNewSpace) { 313 HandleScope scope(isolate); 314 DCHECK(args.length() == 1); 315 CONVERT_SMI_ARG_CHECKED(size, 0); 316 CHECK(IsAligned(size, kPointerSize)); 317 CHECK(size > 0); 318 CHECK(size <= kMaxRegularHeapObjectSize); 319 return *isolate->factory()->NewFillerObject(size, false, NEW_SPACE); 320 } 321 322 323 RUNTIME_FUNCTION(Runtime_AllocateInTargetSpace) { 324 HandleScope scope(isolate); 325 DCHECK(args.length() == 2); 326 CONVERT_SMI_ARG_CHECKED(size, 0); 327 CONVERT_SMI_ARG_CHECKED(flags, 1); 328 CHECK(IsAligned(size, kPointerSize)); 329 CHECK(size > 0); 330 CHECK(size <= kMaxRegularHeapObjectSize); 331 bool double_align = AllocateDoubleAlignFlag::decode(flags); 332 AllocationSpace space = AllocateTargetSpace::decode(flags); 333 return *isolate->factory()->NewFillerObject(size, double_align, space); 334 } 335 336 RUNTIME_FUNCTION(Runtime_AllocateSeqOneByteString) { 337 HandleScope scope(isolate); 338 DCHECK_EQ(1, args.length()); 339 CONVERT_SMI_ARG_CHECKED(length, 0); 340 Handle<SeqOneByteString> result; 341 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 342 isolate, result, isolate->factory()->NewRawOneByteString(length)); 343 return *result; 344 } 345 346 RUNTIME_FUNCTION(Runtime_AllocateSeqTwoByteString) { 347 HandleScope scope(isolate); 348 DCHECK_EQ(1, args.length()); 349 CONVERT_SMI_ARG_CHECKED(length, 0); 350 Handle<SeqTwoByteString> result; 351 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 352 isolate, result, isolate->factory()->NewRawTwoByteString(length)); 353 return *result; 354 } 355 356 357 RUNTIME_FUNCTION(Runtime_IS_VAR) { 358 UNREACHABLE(); // implemented as macro in the parser 359 return NULL; 360 } 361 362 363 namespace { 364 365 bool ComputeLocation(Isolate* isolate, MessageLocation* target) { 366 JavaScriptFrameIterator it(isolate); 367 if (!it.done()) { 368 JavaScriptFrame* frame = it.frame(); 369 JSFunction* fun = frame->function(); 370 Object* script = fun->shared()->script(); 371 if (script->IsScript() && 372 !(Script::cast(script)->source()->IsUndefined(isolate))) { 373 Handle<Script> casted_script(Script::cast(script), isolate); 374 // Compute the location from the function and the relocation info of the 375 // baseline code. For optimized code this will use the deoptimization 376 // information to get canonical location information. 377 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); 378 it.frame()->Summarize(&frames); 379 FrameSummary& summary = frames.last(); 380 int pos = summary.abstract_code()->SourcePosition(summary.code_offset()); 381 *target = MessageLocation(casted_script, pos, pos + 1, handle(fun)); 382 return true; 383 } 384 } 385 return false; 386 } 387 388 389 Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object) { 390 MessageLocation location; 391 if (ComputeLocation(isolate, &location)) { 392 Zone zone(isolate->allocator(), ZONE_NAME); 393 std::unique_ptr<ParseInfo> info( 394 location.function()->shared()->is_function() 395 ? new ParseInfo(&zone, handle(location.function()->shared())) 396 : new ParseInfo(&zone, location.script())); 397 if (Parser::ParseStatic(info.get())) { 398 CallPrinter printer(isolate, location.function()->shared()->IsBuiltin()); 399 Handle<String> str = printer.Print(info->literal(), location.start_pos()); 400 if (str->length() > 0) return str; 401 } else { 402 isolate->clear_pending_exception(); 403 } 404 } 405 return Object::TypeOf(isolate, object); 406 } 407 408 } // namespace 409 410 411 RUNTIME_FUNCTION(Runtime_ThrowCalledNonCallable) { 412 HandleScope scope(isolate); 413 DCHECK_EQ(1, args.length()); 414 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 415 Handle<String> callsite = RenderCallSite(isolate, object); 416 THROW_NEW_ERROR_RETURN_FAILURE( 417 isolate, NewTypeError(MessageTemplate::kCalledNonCallable, callsite)); 418 } 419 420 RUNTIME_FUNCTION(Runtime_ThrowCalledOnNullOrUndefined) { 421 HandleScope scope(isolate); 422 DCHECK_EQ(1, args.length()); 423 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); 424 THROW_NEW_ERROR_RETURN_FAILURE( 425 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, name)); 426 } 427 428 RUNTIME_FUNCTION(Runtime_ThrowConstructedNonConstructable) { 429 HandleScope scope(isolate); 430 DCHECK_EQ(1, args.length()); 431 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 432 Handle<String> callsite = RenderCallSite(isolate, object); 433 THROW_NEW_ERROR_RETURN_FAILURE( 434 isolate, NewTypeError(MessageTemplate::kNotConstructor, callsite)); 435 } 436 437 RUNTIME_FUNCTION(Runtime_ThrowDerivedConstructorReturnedNonObject) { 438 HandleScope scope(isolate); 439 DCHECK_EQ(0, args.length()); 440 THROW_NEW_ERROR_RETURN_FAILURE( 441 isolate, NewTypeError(MessageTemplate::kDerivedConstructorReturn)); 442 } 443 444 RUNTIME_FUNCTION(Runtime_ThrowUndefinedOrNullToObject) { 445 HandleScope scope(isolate); 446 DCHECK_EQ(1, args.length()); 447 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); 448 THROW_NEW_ERROR_RETURN_FAILURE( 449 isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject, name)); 450 } 451 452 // ES6 section 7.3.17 CreateListFromArrayLike (obj) 453 RUNTIME_FUNCTION(Runtime_CreateListFromArrayLike) { 454 HandleScope scope(isolate); 455 DCHECK_EQ(1, args.length()); 456 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 457 RETURN_RESULT_OR_FAILURE(isolate, Object::CreateListFromArrayLike( 458 isolate, object, ElementTypes::kAll)); 459 } 460 461 462 RUNTIME_FUNCTION(Runtime_IncrementUseCounter) { 463 HandleScope scope(isolate); 464 DCHECK_EQ(1, args.length()); 465 CONVERT_SMI_ARG_CHECKED(counter, 0); 466 isolate->CountUsage(static_cast<v8::Isolate::UseCounterFeature>(counter)); 467 return isolate->heap()->undefined_value(); 468 } 469 470 RUNTIME_FUNCTION(Runtime_GetAndResetRuntimeCallStats) { 471 HandleScope scope(isolate); 472 if (args.length() == 0) { 473 // Without arguments, the result is returned as a string. 474 DCHECK_EQ(0, args.length()); 475 std::stringstream stats_stream; 476 isolate->counters()->runtime_call_stats()->Print(stats_stream); 477 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked( 478 stats_stream.str().c_str()); 479 isolate->counters()->runtime_call_stats()->Reset(); 480 return *result; 481 } else { 482 DCHECK_LE(args.length(), 2); 483 std::FILE* f; 484 if (args[0]->IsString()) { 485 // With a string argument, the results are appended to that file. 486 CONVERT_ARG_HANDLE_CHECKED(String, arg0, 0); 487 String::FlatContent flat = arg0->GetFlatContent(); 488 const char* filename = 489 reinterpret_cast<const char*>(&(flat.ToOneByteVector()[0])); 490 f = std::fopen(filename, "a"); 491 DCHECK_NOT_NULL(f); 492 } else { 493 // With an integer argument, the results are written to stdout/stderr. 494 CONVERT_SMI_ARG_CHECKED(fd, 0); 495 DCHECK(fd == 1 || fd == 2); 496 f = fd == 1 ? stdout : stderr; 497 } 498 // The second argument (if any) is a message header to be printed. 499 if (args.length() >= 2) { 500 CONVERT_ARG_HANDLE_CHECKED(String, arg1, 1); 501 arg1->PrintOn(f); 502 std::fputc('\n', f); 503 std::fflush(f); 504 } 505 OFStream stats_stream(f); 506 isolate->counters()->runtime_call_stats()->Print(stats_stream); 507 isolate->counters()->runtime_call_stats()->Reset(); 508 if (args[0]->IsString()) 509 std::fclose(f); 510 else 511 std::fflush(f); 512 return isolate->heap()->undefined_value(); 513 } 514 } 515 516 RUNTIME_FUNCTION(Runtime_OrdinaryHasInstance) { 517 HandleScope scope(isolate); 518 DCHECK_EQ(2, args.length()); 519 CONVERT_ARG_HANDLE_CHECKED(Object, callable, 0); 520 CONVERT_ARG_HANDLE_CHECKED(Object, object, 1); 521 RETURN_RESULT_OR_FAILURE( 522 isolate, Object::OrdinaryHasInstance(isolate, callable, object)); 523 } 524 525 RUNTIME_FUNCTION(Runtime_IsWasmInstance) { 526 HandleScope scope(isolate); 527 DCHECK_EQ(1, args.length()); 528 CONVERT_ARG_CHECKED(Object, object, 0); 529 bool is_wasm_instance = 530 object->IsJSObject() && wasm::IsWasmInstance(JSObject::cast(object)); 531 return *isolate->factory()->ToBoolean(is_wasm_instance); 532 } 533 534 RUNTIME_FUNCTION(Runtime_Typeof) { 535 HandleScope scope(isolate); 536 DCHECK_EQ(1, args.length()); 537 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 538 return *Object::TypeOf(isolate, object); 539 } 540 541 } // namespace internal 542 } // namespace v8 543