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 "src/arguments.h" 8 #include "src/ast/prettyprinter.h" 9 #include "src/bootstrapper.h" 10 #include "src/conversions.h" 11 #include "src/debug/debug.h" 12 #include "src/frames-inl.h" 13 #include "src/isolate-inl.h" 14 #include "src/messages.h" 15 #include "src/parsing/parser.h" 16 17 namespace v8 { 18 namespace internal { 19 20 RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping) { 21 SealHandleScope shs(isolate); 22 DCHECK(args.length() == 0); 23 RUNTIME_ASSERT(isolate->bootstrapper()->IsActive()); 24 return isolate->heap()->undefined_value(); 25 } 26 27 28 RUNTIME_FUNCTION(Runtime_ExportFromRuntime) { 29 HandleScope scope(isolate); 30 DCHECK(args.length() == 1); 31 CONVERT_ARG_HANDLE_CHECKED(JSObject, container, 0); 32 RUNTIME_ASSERT(isolate->bootstrapper()->IsActive()); 33 JSObject::NormalizeProperties(container, KEEP_INOBJECT_PROPERTIES, 10, 34 "ExportFromRuntime"); 35 Bootstrapper::ExportFromRuntime(isolate, container); 36 JSObject::MigrateSlowToFast(container, 0, "ExportFromRuntime"); 37 return *container; 38 } 39 40 41 RUNTIME_FUNCTION(Runtime_ExportExperimentalFromRuntime) { 42 HandleScope scope(isolate); 43 DCHECK(args.length() == 1); 44 CONVERT_ARG_HANDLE_CHECKED(JSObject, container, 0); 45 RUNTIME_ASSERT(isolate->bootstrapper()->IsActive()); 46 JSObject::NormalizeProperties(container, KEEP_INOBJECT_PROPERTIES, 10, 47 "ExportExperimentalFromRuntime"); 48 Bootstrapper::ExportExperimentalFromRuntime(isolate, container); 49 JSObject::MigrateSlowToFast(container, 0, "ExportExperimentalFromRuntime"); 50 return *container; 51 } 52 53 54 RUNTIME_FUNCTION(Runtime_InstallToContext) { 55 HandleScope scope(isolate); 56 DCHECK(args.length() == 1); 57 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); 58 RUNTIME_ASSERT(array->HasFastElements()); 59 RUNTIME_ASSERT(isolate->bootstrapper()->IsActive()); 60 Handle<Context> native_context = isolate->native_context(); 61 Handle<FixedArray> fixed_array(FixedArray::cast(array->elements())); 62 int length = Smi::cast(array->length())->value(); 63 for (int i = 0; i < length; i += 2) { 64 RUNTIME_ASSERT(fixed_array->get(i)->IsString()); 65 Handle<String> name(String::cast(fixed_array->get(i))); 66 RUNTIME_ASSERT(fixed_array->get(i + 1)->IsJSObject()); 67 Handle<JSObject> object(JSObject::cast(fixed_array->get(i + 1))); 68 int index = Context::ImportedFieldIndexForName(name); 69 if (index == Context::kNotFound) { 70 index = Context::IntrinsicIndexForName(name); 71 } 72 RUNTIME_ASSERT(index != Context::kNotFound); 73 native_context->set(index, *object); 74 } 75 return isolate->heap()->undefined_value(); 76 } 77 78 79 RUNTIME_FUNCTION(Runtime_Throw) { 80 HandleScope scope(isolate); 81 DCHECK(args.length() == 1); 82 return isolate->Throw(args[0]); 83 } 84 85 86 RUNTIME_FUNCTION(Runtime_ReThrow) { 87 HandleScope scope(isolate); 88 DCHECK(args.length() == 1); 89 return isolate->ReThrow(args[0]); 90 } 91 92 93 RUNTIME_FUNCTION(Runtime_ThrowStackOverflow) { 94 SealHandleScope shs(isolate); 95 DCHECK_LE(0, args.length()); 96 return isolate->StackOverflow(); 97 } 98 99 100 RUNTIME_FUNCTION(Runtime_UnwindAndFindExceptionHandler) { 101 SealHandleScope shs(isolate); 102 DCHECK(args.length() == 0); 103 return isolate->UnwindAndFindHandler(); 104 } 105 106 107 RUNTIME_FUNCTION(Runtime_PromoteScheduledException) { 108 SealHandleScope shs(isolate); 109 DCHECK(args.length() == 0); 110 return isolate->PromoteScheduledException(); 111 } 112 113 114 RUNTIME_FUNCTION(Runtime_ThrowReferenceError) { 115 HandleScope scope(isolate); 116 DCHECK(args.length() == 1); 117 CONVERT_ARG_HANDLE_CHECKED(Object, name, 0); 118 THROW_NEW_ERROR_RETURN_FAILURE( 119 isolate, NewReferenceError(MessageTemplate::kNotDefined, name)); 120 } 121 122 123 RUNTIME_FUNCTION(Runtime_NewTypeError) { 124 HandleScope scope(isolate); 125 DCHECK(args.length() == 2); 126 CONVERT_INT32_ARG_CHECKED(template_index, 0); 127 CONVERT_ARG_HANDLE_CHECKED(Object, arg0, 1); 128 auto message_template = 129 static_cast<MessageTemplate::Template>(template_index); 130 return *isolate->factory()->NewTypeError(message_template, arg0); 131 } 132 133 134 RUNTIME_FUNCTION(Runtime_NewReferenceError) { 135 HandleScope scope(isolate); 136 DCHECK(args.length() == 2); 137 CONVERT_INT32_ARG_CHECKED(template_index, 0); 138 CONVERT_ARG_HANDLE_CHECKED(Object, arg0, 1); 139 auto message_template = 140 static_cast<MessageTemplate::Template>(template_index); 141 return *isolate->factory()->NewReferenceError(message_template, arg0); 142 } 143 144 145 RUNTIME_FUNCTION(Runtime_NewSyntaxError) { 146 HandleScope scope(isolate); 147 DCHECK(args.length() == 2); 148 CONVERT_INT32_ARG_CHECKED(template_index, 0); 149 CONVERT_ARG_HANDLE_CHECKED(Object, arg0, 1); 150 auto message_template = 151 static_cast<MessageTemplate::Template>(template_index); 152 return *isolate->factory()->NewSyntaxError(message_template, arg0); 153 } 154 155 156 RUNTIME_FUNCTION(Runtime_ThrowIllegalInvocation) { 157 HandleScope scope(isolate); 158 DCHECK(args.length() == 0); 159 THROW_NEW_ERROR_RETURN_FAILURE( 160 isolate, NewTypeError(MessageTemplate::kIllegalInvocation)); 161 } 162 163 164 RUNTIME_FUNCTION(Runtime_ThrowIteratorResultNotAnObject) { 165 HandleScope scope(isolate); 166 DCHECK(args.length() == 1); 167 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0); 168 THROW_NEW_ERROR_RETURN_FAILURE( 169 isolate, 170 NewTypeError(MessageTemplate::kIteratorResultNotAnObject, value)); 171 } 172 173 174 RUNTIME_FUNCTION(Runtime_ThrowStrongModeImplicitConversion) { 175 HandleScope scope(isolate); 176 DCHECK(args.length() == 0); 177 THROW_NEW_ERROR_RETURN_FAILURE( 178 isolate, NewTypeError(MessageTemplate::kStrongImplicitConversion)); 179 } 180 181 182 RUNTIME_FUNCTION(Runtime_ThrowApplyNonFunction) { 183 HandleScope scope(isolate); 184 DCHECK_EQ(1, args.length()); 185 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 186 Handle<String> type = Object::TypeOf(isolate, object); 187 THROW_NEW_ERROR_RETURN_FAILURE( 188 isolate, NewTypeError(MessageTemplate::kApplyNonFunction, object, type)); 189 } 190 191 192 RUNTIME_FUNCTION(Runtime_PromiseRejectEvent) { 193 DCHECK(args.length() == 3); 194 HandleScope scope(isolate); 195 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); 196 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); 197 CONVERT_BOOLEAN_ARG_CHECKED(debug_event, 2); 198 if (debug_event) isolate->debug()->OnPromiseReject(promise, value); 199 Handle<Symbol> key = isolate->factory()->promise_has_handler_symbol(); 200 // Do not report if we actually have a handler. 201 if (JSReceiver::GetDataProperty(promise, key)->IsUndefined()) { 202 isolate->ReportPromiseReject(promise, value, 203 v8::kPromiseRejectWithNoHandler); 204 } 205 return isolate->heap()->undefined_value(); 206 } 207 208 209 RUNTIME_FUNCTION(Runtime_PromiseRevokeReject) { 210 DCHECK(args.length() == 1); 211 HandleScope scope(isolate); 212 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); 213 Handle<Symbol> key = isolate->factory()->promise_has_handler_symbol(); 214 // At this point, no revocation has been issued before 215 RUNTIME_ASSERT(JSReceiver::GetDataProperty(promise, key)->IsUndefined()); 216 isolate->ReportPromiseReject(promise, Handle<Object>(), 217 v8::kPromiseHandlerAddedAfterReject); 218 return isolate->heap()->undefined_value(); 219 } 220 221 222 RUNTIME_FUNCTION(Runtime_StackGuard) { 223 SealHandleScope shs(isolate); 224 DCHECK(args.length() == 0); 225 226 // First check if this is a real stack overflow. 227 StackLimitCheck check(isolate); 228 if (check.JsHasOverflowed()) { 229 return isolate->StackOverflow(); 230 } 231 232 return isolate->stack_guard()->HandleInterrupts(); 233 } 234 235 236 RUNTIME_FUNCTION(Runtime_Interrupt) { 237 SealHandleScope shs(isolate); 238 DCHECK(args.length() == 0); 239 return isolate->stack_guard()->HandleInterrupts(); 240 } 241 242 243 RUNTIME_FUNCTION(Runtime_AllocateInNewSpace) { 244 HandleScope scope(isolate); 245 DCHECK(args.length() == 1); 246 CONVERT_SMI_ARG_CHECKED(size, 0); 247 RUNTIME_ASSERT(IsAligned(size, kPointerSize)); 248 RUNTIME_ASSERT(size > 0); 249 RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize); 250 return *isolate->factory()->NewFillerObject(size, false, NEW_SPACE); 251 } 252 253 254 RUNTIME_FUNCTION(Runtime_AllocateInTargetSpace) { 255 HandleScope scope(isolate); 256 DCHECK(args.length() == 2); 257 CONVERT_SMI_ARG_CHECKED(size, 0); 258 CONVERT_SMI_ARG_CHECKED(flags, 1); 259 RUNTIME_ASSERT(IsAligned(size, kPointerSize)); 260 RUNTIME_ASSERT(size > 0); 261 RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize); 262 bool double_align = AllocateDoubleAlignFlag::decode(flags); 263 AllocationSpace space = AllocateTargetSpace::decode(flags); 264 return *isolate->factory()->NewFillerObject(size, double_align, space); 265 } 266 267 268 // Collect the raw data for a stack trace. Returns an array of 4 269 // element segments each containing a receiver, function, code and 270 // native code offset. 271 RUNTIME_FUNCTION(Runtime_CollectStackTrace) { 272 HandleScope scope(isolate); 273 DCHECK(args.length() == 2); 274 CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0); 275 CONVERT_ARG_HANDLE_CHECKED(Object, caller, 1); 276 277 if (!isolate->bootstrapper()->IsActive()) { 278 // Optionally capture a more detailed stack trace for the message. 279 RETURN_FAILURE_ON_EXCEPTION( 280 isolate, isolate->CaptureAndSetDetailedStackTrace(error_object)); 281 // Capture a simple stack trace for the stack property. 282 RETURN_FAILURE_ON_EXCEPTION( 283 isolate, isolate->CaptureAndSetSimpleStackTrace(error_object, caller)); 284 } 285 return isolate->heap()->undefined_value(); 286 } 287 288 289 RUNTIME_FUNCTION(Runtime_MessageGetStartPosition) { 290 SealHandleScope shs(isolate); 291 DCHECK(args.length() == 1); 292 CONVERT_ARG_CHECKED(JSMessageObject, message, 0); 293 return Smi::FromInt(message->start_position()); 294 } 295 296 297 RUNTIME_FUNCTION(Runtime_MessageGetScript) { 298 SealHandleScope shs(isolate); 299 DCHECK(args.length() == 1); 300 CONVERT_ARG_CHECKED(JSMessageObject, message, 0); 301 return message->script(); 302 } 303 304 305 RUNTIME_FUNCTION(Runtime_FormatMessageString) { 306 HandleScope scope(isolate); 307 DCHECK(args.length() == 4); 308 CONVERT_INT32_ARG_CHECKED(template_index, 0); 309 CONVERT_ARG_HANDLE_CHECKED(String, arg0, 1); 310 CONVERT_ARG_HANDLE_CHECKED(String, arg1, 2); 311 CONVERT_ARG_HANDLE_CHECKED(String, arg2, 3); 312 Handle<String> result; 313 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 314 isolate, result, 315 MessageTemplate::FormatMessage(template_index, arg0, arg1, arg2)); 316 isolate->native_context()->IncrementErrorsThrown(); 317 return *result; 318 } 319 320 321 #define CALLSITE_GET(NAME, RETURN) \ 322 RUNTIME_FUNCTION(Runtime_CallSite##NAME##RT) { \ 323 HandleScope scope(isolate); \ 324 DCHECK(args.length() == 1); \ 325 CONVERT_ARG_HANDLE_CHECKED(JSObject, call_site_obj, 0); \ 326 Handle<String> result; \ 327 CallSite call_site(isolate, call_site_obj); \ 328 RUNTIME_ASSERT(call_site.IsValid()) \ 329 return RETURN(call_site.NAME(), isolate); \ 330 } 331 332 static inline Object* ReturnDereferencedHandle(Handle<Object> obj, 333 Isolate* isolate) { 334 return *obj; 335 } 336 337 338 static inline Object* ReturnPositiveNumberOrNull(int value, Isolate* isolate) { 339 if (value >= 0) return *isolate->factory()->NewNumberFromInt(value); 340 return isolate->heap()->null_value(); 341 } 342 343 344 static inline Object* ReturnBoolean(bool value, Isolate* isolate) { 345 return isolate->heap()->ToBoolean(value); 346 } 347 348 349 CALLSITE_GET(GetFileName, ReturnDereferencedHandle) 350 CALLSITE_GET(GetFunctionName, ReturnDereferencedHandle) 351 CALLSITE_GET(GetScriptNameOrSourceUrl, ReturnDereferencedHandle) 352 CALLSITE_GET(GetMethodName, ReturnDereferencedHandle) 353 CALLSITE_GET(GetLineNumber, ReturnPositiveNumberOrNull) 354 CALLSITE_GET(GetColumnNumber, ReturnPositiveNumberOrNull) 355 CALLSITE_GET(IsNative, ReturnBoolean) 356 CALLSITE_GET(IsToplevel, ReturnBoolean) 357 CALLSITE_GET(IsEval, ReturnBoolean) 358 CALLSITE_GET(IsConstructor, ReturnBoolean) 359 360 #undef CALLSITE_GET 361 362 363 RUNTIME_FUNCTION(Runtime_IS_VAR) { 364 UNREACHABLE(); // implemented as macro in the parser 365 return NULL; 366 } 367 368 369 RUNTIME_FUNCTION(Runtime_IncrementStatsCounter) { 370 SealHandleScope shs(isolate); 371 DCHECK(args.length() == 1); 372 CONVERT_ARG_CHECKED(String, name, 0); 373 374 if (FLAG_native_code_counters) { 375 StatsCounter(isolate, name->ToCString().get()).Increment(); 376 } 377 return isolate->heap()->undefined_value(); 378 } 379 380 381 namespace { 382 383 bool ComputeLocation(Isolate* isolate, MessageLocation* target) { 384 JavaScriptFrameIterator it(isolate); 385 if (!it.done()) { 386 JavaScriptFrame* frame = it.frame(); 387 JSFunction* fun = frame->function(); 388 Object* script = fun->shared()->script(); 389 if (script->IsScript() && 390 !(Script::cast(script)->source()->IsUndefined())) { 391 Handle<Script> casted_script(Script::cast(script)); 392 // Compute the location from the function and the relocation info of the 393 // baseline code. For optimized code this will use the deoptimization 394 // information to get canonical location information. 395 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); 396 it.frame()->Summarize(&frames); 397 FrameSummary& summary = frames.last(); 398 int pos = summary.code()->SourcePosition(summary.pc()); 399 *target = MessageLocation(casted_script, pos, pos + 1, handle(fun)); 400 return true; 401 } 402 } 403 return false; 404 } 405 406 407 Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object) { 408 MessageLocation location; 409 if (ComputeLocation(isolate, &location)) { 410 Zone zone; 411 base::SmartPointer<ParseInfo> info( 412 location.function()->shared()->is_function() 413 ? new ParseInfo(&zone, location.function()) 414 : new ParseInfo(&zone, location.script())); 415 if (Parser::ParseStatic(info.get())) { 416 CallPrinter printer(isolate, location.function()->shared()->IsBuiltin()); 417 const char* string = printer.Print(info->literal(), location.start_pos()); 418 if (strlen(string) > 0) { 419 return isolate->factory()->NewStringFromAsciiChecked(string); 420 } 421 } else { 422 isolate->clear_pending_exception(); 423 } 424 } 425 return Object::TypeOf(isolate, object); 426 } 427 428 } // namespace 429 430 431 RUNTIME_FUNCTION(Runtime_ThrowCalledNonCallable) { 432 HandleScope scope(isolate); 433 DCHECK_EQ(1, args.length()); 434 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 435 Handle<String> callsite = RenderCallSite(isolate, object); 436 THROW_NEW_ERROR_RETURN_FAILURE( 437 isolate, NewTypeError(MessageTemplate::kCalledNonCallable, callsite)); 438 } 439 440 441 RUNTIME_FUNCTION(Runtime_ThrowConstructedNonConstructable) { 442 HandleScope scope(isolate); 443 DCHECK_EQ(1, args.length()); 444 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 445 Handle<String> callsite = RenderCallSite(isolate, object); 446 THROW_NEW_ERROR_RETURN_FAILURE( 447 isolate, NewTypeError(MessageTemplate::kNotConstructor, callsite)); 448 } 449 450 451 // ES6 section 7.3.17 CreateListFromArrayLike (obj) 452 RUNTIME_FUNCTION(Runtime_CreateListFromArrayLike) { 453 HandleScope scope(isolate); 454 DCHECK_EQ(1, args.length()); 455 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 456 Handle<FixedArray> result; 457 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 458 isolate, result, 459 Object::CreateListFromArrayLike(isolate, object, ElementTypes::kAll)); 460 return *result; 461 } 462 463 464 RUNTIME_FUNCTION(Runtime_IncrementUseCounter) { 465 HandleScope scope(isolate); 466 DCHECK_EQ(1, args.length()); 467 CONVERT_SMI_ARG_CHECKED(counter, 0); 468 isolate->CountUsage(static_cast<v8::Isolate::UseCounterFeature>(counter)); 469 return isolate->heap()->undefined_value(); 470 } 471 472 } // namespace internal 473 } // namespace v8 474