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/debug/debug-evaluate.h" 9 #include "src/debug/debug-frames.h" 10 #include "src/debug/debug-scopes.h" 11 #include "src/debug/debug.h" 12 #include "src/frames-inl.h" 13 #include "src/interpreter/bytecodes.h" 14 #include "src/interpreter/interpreter.h" 15 #include "src/isolate-inl.h" 16 #include "src/runtime/runtime.h" 17 18 namespace v8 { 19 namespace internal { 20 21 RUNTIME_FUNCTION(Runtime_DebugBreak) { 22 SealHandleScope shs(isolate); 23 DCHECK(args.length() == 1); 24 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0); 25 isolate->debug()->set_return_value(value); 26 27 // Get the top-most JavaScript frame. 28 JavaScriptFrameIterator it(isolate); 29 isolate->debug()->Break(it.frame()); 30 31 isolate->debug()->SetAfterBreakTarget(it.frame()); 32 return *isolate->debug()->return_value(); 33 } 34 35 RUNTIME_FUNCTION(Runtime_DebugBreakOnBytecode) { 36 SealHandleScope shs(isolate); 37 DCHECK(args.length() == 1); 38 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0); 39 isolate->debug()->set_return_value(value); 40 41 // Get the top-most JavaScript frame. 42 JavaScriptFrameIterator it(isolate); 43 isolate->debug()->Break(it.frame()); 44 45 // If live-edit has dropped frames, we are not going back to dispatch. 46 if (LiveEdit::SetAfterBreakTarget(isolate->debug())) return Smi::FromInt(0); 47 48 // Return the handler from the original bytecode array. 49 DCHECK(it.frame()->is_interpreted()); 50 InterpretedFrame* interpreted_frame = 51 reinterpret_cast<InterpretedFrame*>(it.frame()); 52 SharedFunctionInfo* shared = interpreted_frame->function()->shared(); 53 BytecodeArray* bytecode_array = shared->bytecode_array(); 54 int bytecode_offset = interpreted_frame->GetBytecodeOffset(); 55 interpreter::Bytecode bytecode = 56 interpreter::Bytecodes::FromByte(bytecode_array->get(bytecode_offset)); 57 return isolate->interpreter()->GetBytecodeHandler( 58 bytecode, interpreter::OperandScale::kSingle); 59 } 60 61 62 RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) { 63 SealHandleScope shs(isolate); 64 DCHECK(args.length() == 0); 65 if (isolate->debug()->break_points_active()) { 66 isolate->debug()->HandleDebugBreak(); 67 } 68 return isolate->heap()->undefined_value(); 69 } 70 71 72 // Adds a JavaScript function as a debug event listener. 73 // args[0]: debug event listener function to set or null or undefined for 74 // clearing the event listener function 75 // args[1]: object supplied during callback 76 RUNTIME_FUNCTION(Runtime_SetDebugEventListener) { 77 SealHandleScope shs(isolate); 78 DCHECK(args.length() == 2); 79 RUNTIME_ASSERT(args[0]->IsJSFunction() || args[0]->IsUndefined(isolate) || 80 args[0]->IsNull(isolate)); 81 CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0); 82 CONVERT_ARG_HANDLE_CHECKED(Object, data, 1); 83 isolate->debug()->SetEventListener(callback, data); 84 85 return isolate->heap()->undefined_value(); 86 } 87 88 89 RUNTIME_FUNCTION(Runtime_ScheduleBreak) { 90 SealHandleScope shs(isolate); 91 DCHECK(args.length() == 0); 92 isolate->stack_guard()->RequestDebugBreak(); 93 return isolate->heap()->undefined_value(); 94 } 95 96 97 static Handle<Object> DebugGetProperty(LookupIterator* it, 98 bool* has_caught = NULL) { 99 for (; it->IsFound(); it->Next()) { 100 switch (it->state()) { 101 case LookupIterator::NOT_FOUND: 102 case LookupIterator::TRANSITION: 103 UNREACHABLE(); 104 case LookupIterator::ACCESS_CHECK: 105 // Ignore access checks. 106 break; 107 case LookupIterator::INTEGER_INDEXED_EXOTIC: 108 case LookupIterator::INTERCEPTOR: 109 case LookupIterator::JSPROXY: 110 return it->isolate()->factory()->undefined_value(); 111 case LookupIterator::ACCESSOR: { 112 Handle<Object> accessors = it->GetAccessors(); 113 if (!accessors->IsAccessorInfo()) { 114 return it->isolate()->factory()->undefined_value(); 115 } 116 MaybeHandle<Object> maybe_result = 117 JSObject::GetPropertyWithAccessor(it); 118 Handle<Object> result; 119 if (!maybe_result.ToHandle(&result)) { 120 result = handle(it->isolate()->pending_exception(), it->isolate()); 121 it->isolate()->clear_pending_exception(); 122 if (has_caught != NULL) *has_caught = true; 123 } 124 return result; 125 } 126 127 case LookupIterator::DATA: 128 return it->GetDataValue(); 129 } 130 } 131 132 return it->isolate()->factory()->undefined_value(); 133 } 134 135 136 static Handle<Object> DebugGetProperty(Handle<Object> object, 137 Handle<Name> name) { 138 LookupIterator it(object, name); 139 return DebugGetProperty(&it); 140 } 141 142 143 template <class IteratorType> 144 static MaybeHandle<JSArray> GetIteratorInternalProperties( 145 Isolate* isolate, Handle<IteratorType> object) { 146 Factory* factory = isolate->factory(); 147 Handle<IteratorType> iterator = Handle<IteratorType>::cast(object); 148 CHECK(iterator->kind()->IsSmi()); 149 const char* kind = NULL; 150 switch (Smi::cast(iterator->kind())->value()) { 151 case IteratorType::kKindKeys: 152 kind = "keys"; 153 break; 154 case IteratorType::kKindValues: 155 kind = "values"; 156 break; 157 case IteratorType::kKindEntries: 158 kind = "entries"; 159 break; 160 default: 161 UNREACHABLE(); 162 } 163 164 Handle<FixedArray> result = factory->NewFixedArray(2 * 3); 165 Handle<String> has_more = 166 factory->NewStringFromAsciiChecked("[[IteratorHasMore]]"); 167 result->set(0, *has_more); 168 result->set(1, isolate->heap()->ToBoolean(iterator->HasMore())); 169 170 Handle<String> index = 171 factory->NewStringFromAsciiChecked("[[IteratorIndex]]"); 172 result->set(2, *index); 173 result->set(3, iterator->index()); 174 175 Handle<String> iterator_kind = 176 factory->NewStringFromAsciiChecked("[[IteratorKind]]"); 177 result->set(4, *iterator_kind); 178 Handle<String> kind_str = factory->NewStringFromAsciiChecked(kind); 179 result->set(5, *kind_str); 180 return factory->NewJSArrayWithElements(result); 181 } 182 183 184 MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate, 185 Handle<Object> object) { 186 Factory* factory = isolate->factory(); 187 if (object->IsJSBoundFunction()) { 188 Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object); 189 190 Handle<FixedArray> result = factory->NewFixedArray(2 * 3); 191 Handle<String> target = 192 factory->NewStringFromAsciiChecked("[[TargetFunction]]"); 193 result->set(0, *target); 194 result->set(1, function->bound_target_function()); 195 196 Handle<String> bound_this = 197 factory->NewStringFromAsciiChecked("[[BoundThis]]"); 198 result->set(2, *bound_this); 199 result->set(3, function->bound_this()); 200 201 Handle<String> bound_args = 202 factory->NewStringFromAsciiChecked("[[BoundArgs]]"); 203 result->set(4, *bound_args); 204 Handle<FixedArray> bound_arguments = 205 factory->CopyFixedArray(handle(function->bound_arguments(), isolate)); 206 Handle<JSArray> arguments_array = 207 factory->NewJSArrayWithElements(bound_arguments); 208 result->set(5, *arguments_array); 209 return factory->NewJSArrayWithElements(result); 210 } else if (object->IsJSMapIterator()) { 211 Handle<JSMapIterator> iterator = Handle<JSMapIterator>::cast(object); 212 return GetIteratorInternalProperties(isolate, iterator); 213 } else if (object->IsJSSetIterator()) { 214 Handle<JSSetIterator> iterator = Handle<JSSetIterator>::cast(object); 215 return GetIteratorInternalProperties(isolate, iterator); 216 } else if (object->IsJSGeneratorObject()) { 217 Handle<JSGeneratorObject> generator = 218 Handle<JSGeneratorObject>::cast(object); 219 220 const char* status = "suspended"; 221 if (generator->is_closed()) { 222 status = "closed"; 223 } else if (generator->is_executing()) { 224 status = "running"; 225 } else { 226 DCHECK(generator->is_suspended()); 227 } 228 229 Handle<FixedArray> result = factory->NewFixedArray(2 * 3); 230 Handle<String> generator_status = 231 factory->NewStringFromAsciiChecked("[[GeneratorStatus]]"); 232 result->set(0, *generator_status); 233 Handle<String> status_str = factory->NewStringFromAsciiChecked(status); 234 result->set(1, *status_str); 235 236 Handle<String> function = 237 factory->NewStringFromAsciiChecked("[[GeneratorFunction]]"); 238 result->set(2, *function); 239 result->set(3, generator->function()); 240 241 Handle<String> receiver = 242 factory->NewStringFromAsciiChecked("[[GeneratorReceiver]]"); 243 result->set(4, *receiver); 244 result->set(5, generator->receiver()); 245 return factory->NewJSArrayWithElements(result); 246 } else if (object->IsJSPromise()) { 247 Handle<JSObject> promise = Handle<JSObject>::cast(object); 248 249 Handle<Object> status_obj = 250 DebugGetProperty(promise, isolate->factory()->promise_state_symbol()); 251 CHECK(status_obj->IsSmi()); 252 const char* status = "rejected"; 253 int status_val = Handle<Smi>::cast(status_obj)->value(); 254 switch (status_val) { 255 case +1: 256 status = "resolved"; 257 break; 258 case 0: 259 status = "pending"; 260 break; 261 default: 262 DCHECK_EQ(-1, status_val); 263 } 264 265 Handle<FixedArray> result = factory->NewFixedArray(2 * 2); 266 Handle<String> promise_status = 267 factory->NewStringFromAsciiChecked("[[PromiseStatus]]"); 268 result->set(0, *promise_status); 269 Handle<String> status_str = factory->NewStringFromAsciiChecked(status); 270 result->set(1, *status_str); 271 272 Handle<Object> value_obj = 273 DebugGetProperty(promise, isolate->factory()->promise_result_symbol()); 274 Handle<String> promise_value = 275 factory->NewStringFromAsciiChecked("[[PromiseValue]]"); 276 result->set(2, *promise_value); 277 result->set(3, *value_obj); 278 return factory->NewJSArrayWithElements(result); 279 } else if (object->IsJSProxy()) { 280 Handle<JSProxy> js_proxy = Handle<JSProxy>::cast(object); 281 Handle<FixedArray> result = factory->NewFixedArray(3 * 2); 282 283 Handle<String> handler_str = 284 factory->NewStringFromAsciiChecked("[[Handler]]"); 285 result->set(0, *handler_str); 286 result->set(1, js_proxy->handler()); 287 288 Handle<String> target_str = 289 factory->NewStringFromAsciiChecked("[[Target]]"); 290 result->set(2, *target_str); 291 result->set(3, js_proxy->target()); 292 293 Handle<String> is_revoked_str = 294 factory->NewStringFromAsciiChecked("[[IsRevoked]]"); 295 result->set(4, *is_revoked_str); 296 result->set(5, isolate->heap()->ToBoolean(js_proxy->IsRevoked())); 297 return factory->NewJSArrayWithElements(result); 298 } else if (object->IsJSValue()) { 299 Handle<JSValue> js_value = Handle<JSValue>::cast(object); 300 301 Handle<FixedArray> result = factory->NewFixedArray(2); 302 Handle<String> primitive_value = 303 factory->NewStringFromAsciiChecked("[[PrimitiveValue]]"); 304 result->set(0, *primitive_value); 305 result->set(1, js_value->value()); 306 return factory->NewJSArrayWithElements(result); 307 } 308 return factory->NewJSArray(0); 309 } 310 311 312 RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties) { 313 HandleScope scope(isolate); 314 DCHECK(args.length() == 1); 315 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0); 316 RETURN_RESULT_OR_FAILURE(isolate, 317 Runtime::GetInternalProperties(isolate, obj)); 318 } 319 320 321 // Get debugger related details for an object property, in the following format: 322 // 0: Property value 323 // 1: Property details 324 // 2: Property value is exception 325 // 3: Getter function if defined 326 // 4: Setter function if defined 327 // Items 2-4 are only filled if the property has either a getter or a setter. 328 RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) { 329 HandleScope scope(isolate); 330 331 DCHECK(args.length() == 2); 332 333 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); 334 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); 335 336 // Make sure to set the current context to the context before the debugger was 337 // entered (if the debugger is entered). The reason for switching context here 338 // is that for some property lookups (accessors and interceptors) callbacks 339 // into the embedding application can occour, and the embedding application 340 // could have the assumption that its own native context is the current 341 // context and not some internal debugger context. 342 SaveContext save(isolate); 343 if (isolate->debug()->in_debug_scope()) { 344 isolate->set_context(*isolate->debug()->debugger_entry()->GetContext()); 345 } 346 347 // Check if the name is trivially convertible to an index and get the element 348 // if so. 349 uint32_t index; 350 // TODO(verwaest): Make sure DebugGetProperty can handle arrays, and remove 351 // this special case. 352 if (name->AsArrayIndex(&index)) { 353 Handle<FixedArray> details = isolate->factory()->NewFixedArray(2); 354 Handle<Object> element_or_char; 355 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 356 isolate, element_or_char, JSReceiver::GetElement(isolate, obj, index)); 357 details->set(0, *element_or_char); 358 details->set(1, PropertyDetails::Empty().AsSmi()); 359 return *isolate->factory()->NewJSArrayWithElements(details); 360 } 361 362 LookupIterator it(obj, name, LookupIterator::OWN); 363 bool has_caught = false; 364 Handle<Object> value = DebugGetProperty(&it, &has_caught); 365 if (!it.IsFound()) return isolate->heap()->undefined_value(); 366 367 Handle<Object> maybe_pair; 368 if (it.state() == LookupIterator::ACCESSOR) { 369 maybe_pair = it.GetAccessors(); 370 } 371 372 // If the callback object is a fixed array then it contains JavaScript 373 // getter and/or setter. 374 bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair(); 375 Handle<FixedArray> details = 376 isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3); 377 details->set(0, *value); 378 // TODO(verwaest): Get rid of this random way of handling interceptors. 379 PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR 380 ? PropertyDetails::Empty() 381 : it.property_details(); 382 details->set(1, d.AsSmi()); 383 details->set( 384 2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR)); 385 if (has_js_accessors) { 386 Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(maybe_pair); 387 details->set(3, isolate->heap()->ToBoolean(has_caught)); 388 Handle<Object> getter = 389 AccessorPair::GetComponent(accessors, ACCESSOR_GETTER); 390 Handle<Object> setter = 391 AccessorPair::GetComponent(accessors, ACCESSOR_SETTER); 392 details->set(4, *getter); 393 details->set(5, *setter); 394 } 395 396 return *isolate->factory()->NewJSArrayWithElements(details); 397 } 398 399 400 RUNTIME_FUNCTION(Runtime_DebugGetProperty) { 401 HandleScope scope(isolate); 402 403 DCHECK(args.length() == 2); 404 405 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); 406 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); 407 408 LookupIterator it(obj, name); 409 return *DebugGetProperty(&it); 410 } 411 412 413 // Return the property type calculated from the property details. 414 // args[0]: smi with property details. 415 RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails) { 416 SealHandleScope shs(isolate); 417 DCHECK(args.length() == 1); 418 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0); 419 return Smi::FromInt(static_cast<int>(details.type())); 420 } 421 422 423 // Return the property attribute calculated from the property details. 424 // args[0]: smi with property details. 425 RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) { 426 SealHandleScope shs(isolate); 427 DCHECK(args.length() == 1); 428 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0); 429 return Smi::FromInt(static_cast<int>(details.attributes())); 430 } 431 432 433 RUNTIME_FUNCTION(Runtime_CheckExecutionState) { 434 SealHandleScope shs(isolate); 435 DCHECK(args.length() == 1); 436 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); 437 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); 438 return isolate->heap()->true_value(); 439 } 440 441 442 RUNTIME_FUNCTION(Runtime_GetFrameCount) { 443 HandleScope scope(isolate); 444 DCHECK(args.length() == 1); 445 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); 446 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); 447 448 // Count all frames which are relevant to debugging stack trace. 449 int n = 0; 450 StackFrame::Id id = isolate->debug()->break_frame_id(); 451 if (id == StackFrame::NO_ID) { 452 // If there is no JavaScript stack frame count is 0. 453 return Smi::FromInt(0); 454 } 455 456 for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) { 457 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); 458 it.frame()->Summarize(&frames); 459 for (int i = frames.length() - 1; i >= 0; i--) { 460 // Omit functions from native and extension scripts. 461 if (frames[i].function()->shared()->IsSubjectToDebugging()) n++; 462 } 463 } 464 return Smi::FromInt(n); 465 } 466 467 468 static const int kFrameDetailsFrameIdIndex = 0; 469 static const int kFrameDetailsReceiverIndex = 1; 470 static const int kFrameDetailsFunctionIndex = 2; 471 static const int kFrameDetailsArgumentCountIndex = 3; 472 static const int kFrameDetailsLocalCountIndex = 4; 473 static const int kFrameDetailsSourcePositionIndex = 5; 474 static const int kFrameDetailsConstructCallIndex = 6; 475 static const int kFrameDetailsAtReturnIndex = 7; 476 static const int kFrameDetailsFlagsIndex = 8; 477 static const int kFrameDetailsFirstDynamicIndex = 9; 478 479 480 // Return an array with frame details 481 // args[0]: number: break id 482 // args[1]: number: frame index 483 // 484 // The array returned contains the following information: 485 // 0: Frame id 486 // 1: Receiver 487 // 2: Function 488 // 3: Argument count 489 // 4: Local count 490 // 5: Source position 491 // 6: Constructor call 492 // 7: Is at return 493 // 8: Flags 494 // Arguments name, value 495 // Locals name, value 496 // Return value if any 497 RUNTIME_FUNCTION(Runtime_GetFrameDetails) { 498 HandleScope scope(isolate); 499 DCHECK(args.length() == 2); 500 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); 501 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); 502 503 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); 504 Heap* heap = isolate->heap(); 505 506 // Find the relevant frame with the requested index. 507 StackFrame::Id id = isolate->debug()->break_frame_id(); 508 if (id == StackFrame::NO_ID) { 509 // If there are no JavaScript stack frames return undefined. 510 return heap->undefined_value(); 511 } 512 513 JavaScriptFrameIterator it(isolate, id); 514 // Inlined frame index in optimized frame, starting from outer function. 515 int inlined_jsframe_index = 516 DebugFrameHelper::FindIndexedNonNativeFrame(&it, index); 517 if (inlined_jsframe_index == -1) return heap->undefined_value(); 518 519 FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate); 520 bool is_optimized = it.frame()->is_optimized(); 521 522 // Traverse the saved contexts chain to find the active context for the 523 // selected frame. 524 SaveContext* save = 525 DebugFrameHelper::FindSavedContextForFrame(isolate, it.frame()); 526 527 // Get the frame id. 528 Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()), 529 isolate); 530 531 // Find source position in unoptimized code. 532 int position = frame_inspector.GetSourcePosition(); 533 534 // Check for constructor frame. 535 bool constructor = frame_inspector.IsConstructor(); 536 537 // Get scope info and read from it for local variable information. 538 Handle<JSFunction> function = 539 Handle<JSFunction>::cast(frame_inspector.GetFunction()); 540 RUNTIME_ASSERT(function->shared()->IsSubjectToDebugging()); 541 Handle<SharedFunctionInfo> shared(function->shared()); 542 Handle<ScopeInfo> scope_info(shared->scope_info()); 543 DCHECK(*scope_info != ScopeInfo::Empty(isolate)); 544 545 // Get the locals names and values into a temporary array. 546 int local_count = scope_info->LocalCount(); 547 for (int slot = 0; slot < scope_info->LocalCount(); ++slot) { 548 // Hide compiler-introduced temporary variables, whether on the stack or on 549 // the context. 550 if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(slot))) { 551 local_count--; 552 } 553 } 554 555 Handle<FixedArray> locals = 556 isolate->factory()->NewFixedArray(local_count * 2); 557 558 // Fill in the values of the locals. 559 int local = 0; 560 int i = 0; 561 for (; i < scope_info->StackLocalCount(); ++i) { 562 // Use the value from the stack. 563 if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(i))) continue; 564 locals->set(local * 2, scope_info->LocalName(i)); 565 Handle<Object> value = 566 frame_inspector.GetExpression(scope_info->StackLocalIndex(i)); 567 // TODO(yangguo): We convert optimized out values to {undefined} when they 568 // are passed to the debugger. Eventually we should handle them somehow. 569 if (value->IsOptimizedOut(isolate)) { 570 value = isolate->factory()->undefined_value(); 571 } 572 locals->set(local * 2 + 1, *value); 573 local++; 574 } 575 if (local < local_count) { 576 // Get the context containing declarations. 577 Handle<Context> context( 578 Handle<Context>::cast(frame_inspector.GetContext())->closure_context()); 579 for (; i < scope_info->LocalCount(); ++i) { 580 Handle<String> name(scope_info->LocalName(i)); 581 if (ScopeInfo::VariableIsSynthetic(*name)) continue; 582 VariableMode mode; 583 InitializationFlag init_flag; 584 MaybeAssignedFlag maybe_assigned_flag; 585 locals->set(local * 2, *name); 586 int context_slot_index = ScopeInfo::ContextSlotIndex( 587 scope_info, name, &mode, &init_flag, &maybe_assigned_flag); 588 Object* value = context->get(context_slot_index); 589 locals->set(local * 2 + 1, value); 590 local++; 591 } 592 } 593 594 // Check whether this frame is positioned at return. If not top 595 // frame or if the frame is optimized it cannot be at a return. 596 bool at_return = false; 597 if (!is_optimized && index == 0) { 598 at_return = isolate->debug()->IsBreakAtReturn(it.frame()); 599 } 600 601 // If positioned just before return find the value to be returned and add it 602 // to the frame information. 603 Handle<Object> return_value = isolate->factory()->undefined_value(); 604 if (at_return) { 605 return_value = isolate->debug()->return_value(); 606 } 607 608 // Now advance to the arguments adapter frame (if any). It contains all 609 // the provided parameters whereas the function frame always have the number 610 // of arguments matching the functions parameters. The rest of the 611 // information (except for what is collected above) is the same. 612 if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) { 613 it.AdvanceToArgumentsFrame(); 614 frame_inspector.SetArgumentsFrame(it.frame()); 615 } 616 617 // Find the number of arguments to fill. At least fill the number of 618 // parameters for the function and fill more if more parameters are provided. 619 int argument_count = scope_info->ParameterCount(); 620 if (argument_count < frame_inspector.GetParametersCount()) { 621 argument_count = frame_inspector.GetParametersCount(); 622 } 623 624 // Calculate the size of the result. 625 int details_size = kFrameDetailsFirstDynamicIndex + 626 2 * (argument_count + local_count) + (at_return ? 1 : 0); 627 Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size); 628 629 // Add the frame id. 630 details->set(kFrameDetailsFrameIdIndex, *frame_id); 631 632 // Add the function (same as in function frame). 633 details->set(kFrameDetailsFunctionIndex, *(frame_inspector.GetFunction())); 634 635 // Add the arguments count. 636 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count)); 637 638 // Add the locals count 639 details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(local_count)); 640 641 // Add the source position. 642 if (position != RelocInfo::kNoPosition) { 643 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position)); 644 } else { 645 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value()); 646 } 647 648 // Add the constructor information. 649 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor)); 650 651 // Add the at return information. 652 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return)); 653 654 // Add flags to indicate information on whether this frame is 655 // bit 0: invoked in the debugger context. 656 // bit 1: optimized frame. 657 // bit 2: inlined in optimized frame 658 int flags = 0; 659 if (*save->context() == *isolate->debug()->debug_context()) { 660 flags |= 1 << 0; 661 } 662 if (is_optimized) { 663 flags |= 1 << 1; 664 flags |= inlined_jsframe_index << 2; 665 } 666 details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags)); 667 668 // Fill the dynamic part. 669 int details_index = kFrameDetailsFirstDynamicIndex; 670 671 // Add arguments name and value. 672 for (int i = 0; i < argument_count; i++) { 673 // Name of the argument. 674 if (i < scope_info->ParameterCount()) { 675 details->set(details_index++, scope_info->ParameterName(i)); 676 } else { 677 details->set(details_index++, heap->undefined_value()); 678 } 679 680 // Parameter value. 681 if (i < frame_inspector.GetParametersCount()) { 682 // Get the value from the stack. 683 details->set(details_index++, *(frame_inspector.GetParameter(i))); 684 } else { 685 details->set(details_index++, heap->undefined_value()); 686 } 687 } 688 689 // Add locals name and value from the temporary copy from the function frame. 690 for (int i = 0; i < local_count * 2; i++) { 691 details->set(details_index++, locals->get(i)); 692 } 693 694 // Add the value being returned. 695 if (at_return) { 696 details->set(details_index++, *return_value); 697 } 698 699 // Add the receiver (same as in function frame). 700 Handle<Object> receiver(it.frame()->receiver(), isolate); 701 DCHECK(!function->shared()->IsBuiltin()); 702 DCHECK_IMPLIES(is_sloppy(shared->language_mode()), receiver->IsJSReceiver()); 703 details->set(kFrameDetailsReceiverIndex, *receiver); 704 705 DCHECK_EQ(details_size, details_index); 706 return *isolate->factory()->NewJSArrayWithElements(details); 707 } 708 709 710 RUNTIME_FUNCTION(Runtime_GetScopeCount) { 711 HandleScope scope(isolate); 712 DCHECK(args.length() == 2); 713 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); 714 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); 715 716 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); 717 718 // Get the frame where the debugging is performed. 719 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); 720 JavaScriptFrameIterator it(isolate, id); 721 JavaScriptFrame* frame = it.frame(); 722 FrameInspector frame_inspector(frame, 0, isolate); 723 724 // Count the visible scopes. 725 int n = 0; 726 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) { 727 n++; 728 } 729 730 return Smi::FromInt(n); 731 } 732 733 734 // Return an array with scope details 735 // args[0]: number: break id 736 // args[1]: number: frame index 737 // args[2]: number: inlined frame index 738 // args[3]: number: scope index 739 // 740 // The array returned contains the following information: 741 // 0: Scope type 742 // 1: Scope object 743 RUNTIME_FUNCTION(Runtime_GetScopeDetails) { 744 HandleScope scope(isolate); 745 DCHECK(args.length() == 4); 746 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); 747 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); 748 749 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); 750 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); 751 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]); 752 753 // Get the frame where the debugging is performed. 754 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); 755 JavaScriptFrameIterator frame_it(isolate, id); 756 JavaScriptFrame* frame = frame_it.frame(); 757 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); 758 759 // Find the requested scope. 760 int n = 0; 761 ScopeIterator it(isolate, &frame_inspector); 762 for (; !it.Done() && n < index; it.Next()) { 763 n++; 764 } 765 if (it.Done()) { 766 return isolate->heap()->undefined_value(); 767 } 768 RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails()); 769 } 770 771 772 // Return an array of scope details 773 // args[0]: number: break id 774 // args[1]: number: frame index 775 // args[2]: number: inlined frame index 776 // args[3]: boolean: ignore nested scopes 777 // 778 // The array returned contains arrays with the following information: 779 // 0: Scope type 780 // 1: Scope object 781 RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) { 782 HandleScope scope(isolate); 783 DCHECK(args.length() == 3 || args.length() == 4); 784 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); 785 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); 786 787 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); 788 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); 789 790 ScopeIterator::Option option = ScopeIterator::DEFAULT; 791 if (args.length() == 4) { 792 CONVERT_BOOLEAN_ARG_CHECKED(flag, 3); 793 if (flag) option = ScopeIterator::IGNORE_NESTED_SCOPES; 794 } 795 796 // Get the frame where the debugging is performed. 797 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); 798 JavaScriptFrameIterator frame_it(isolate, id); 799 JavaScriptFrame* frame = frame_it.frame(); 800 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); 801 802 List<Handle<JSObject> > result(4); 803 ScopeIterator it(isolate, &frame_inspector, option); 804 for (; !it.Done(); it.Next()) { 805 Handle<JSObject> details; 806 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details, 807 it.MaterializeScopeDetails()); 808 result.Add(details); 809 } 810 811 Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length()); 812 for (int i = 0; i < result.length(); ++i) { 813 array->set(i, *result[i]); 814 } 815 return *isolate->factory()->NewJSArrayWithElements(array); 816 } 817 818 819 RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) { 820 HandleScope scope(isolate); 821 DCHECK_EQ(1, args.length()); 822 823 // Check arguments. 824 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); 825 826 // Count the visible scopes. 827 int n = 0; 828 if (function->IsJSFunction()) { 829 for (ScopeIterator it(isolate, Handle<JSFunction>::cast(function)); 830 !it.Done(); it.Next()) { 831 n++; 832 } 833 } 834 835 return Smi::FromInt(n); 836 } 837 838 839 RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) { 840 HandleScope scope(isolate); 841 DCHECK(args.length() == 2); 842 843 // Check arguments. 844 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); 845 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); 846 847 // Find the requested scope. 848 int n = 0; 849 ScopeIterator it(isolate, fun); 850 for (; !it.Done() && n < index; it.Next()) { 851 n++; 852 } 853 if (it.Done()) { 854 return isolate->heap()->undefined_value(); 855 } 856 857 RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails()); 858 } 859 860 861 static bool SetScopeVariableValue(ScopeIterator* it, int index, 862 Handle<String> variable_name, 863 Handle<Object> new_value) { 864 for (int n = 0; !it->Done() && n < index; it->Next()) { 865 n++; 866 } 867 if (it->Done()) { 868 return false; 869 } 870 return it->SetVariableValue(variable_name, new_value); 871 } 872 873 874 // Change variable value in closure or local scope 875 // args[0]: number or JsFunction: break id or function 876 // args[1]: number: frame index (when arg[0] is break id) 877 // args[2]: number: inlined frame index (when arg[0] is break id) 878 // args[3]: number: scope index 879 // args[4]: string: variable name 880 // args[5]: object: new value 881 // 882 // Return true if success and false otherwise 883 RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) { 884 HandleScope scope(isolate); 885 DCHECK(args.length() == 6); 886 887 // Check arguments. 888 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]); 889 CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4); 890 CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5); 891 892 bool res; 893 if (args[0]->IsNumber()) { 894 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); 895 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); 896 897 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); 898 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); 899 900 // Get the frame where the debugging is performed. 901 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); 902 JavaScriptFrameIterator frame_it(isolate, id); 903 JavaScriptFrame* frame = frame_it.frame(); 904 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); 905 906 ScopeIterator it(isolate, &frame_inspector); 907 res = SetScopeVariableValue(&it, index, variable_name, new_value); 908 } else { 909 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); 910 ScopeIterator it(isolate, fun); 911 res = SetScopeVariableValue(&it, index, variable_name, new_value); 912 } 913 914 return isolate->heap()->ToBoolean(res); 915 } 916 917 918 RUNTIME_FUNCTION(Runtime_DebugPrintScopes) { 919 HandleScope scope(isolate); 920 DCHECK(args.length() == 0); 921 922 #ifdef DEBUG 923 // Print the scopes for the top frame. 924 StackFrameLocator locator(isolate); 925 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); 926 FrameInspector frame_inspector(frame, 0, isolate); 927 928 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) { 929 it.DebugPrint(); 930 } 931 #endif 932 return isolate->heap()->undefined_value(); 933 } 934 935 936 // Sets the disable break state 937 // args[0]: disable break state 938 RUNTIME_FUNCTION(Runtime_SetBreakPointsActive) { 939 HandleScope scope(isolate); 940 DCHECK(args.length() == 1); 941 CONVERT_BOOLEAN_ARG_CHECKED(active, 0); 942 isolate->debug()->set_break_points_active(active); 943 return isolate->heap()->undefined_value(); 944 } 945 946 947 static bool IsPositionAlignmentCodeCorrect(int alignment) { 948 return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED; 949 } 950 951 952 RUNTIME_FUNCTION(Runtime_GetBreakLocations) { 953 HandleScope scope(isolate); 954 DCHECK(args.length() == 2); 955 RUNTIME_ASSERT(isolate->debug()->is_active()); 956 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); 957 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]); 958 959 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) { 960 return isolate->ThrowIllegalOperation(); 961 } 962 BreakPositionAlignment alignment = 963 static_cast<BreakPositionAlignment>(statement_aligned_code); 964 965 Handle<SharedFunctionInfo> shared(fun->shared()); 966 // Find the number of break points 967 Handle<Object> break_locations = 968 Debug::GetSourceBreakLocations(shared, alignment); 969 if (break_locations->IsUndefined(isolate)) { 970 return isolate->heap()->undefined_value(); 971 } 972 // Return array as JS array 973 return *isolate->factory()->NewJSArrayWithElements( 974 Handle<FixedArray>::cast(break_locations)); 975 } 976 977 978 // Set a break point in a function. 979 // args[0]: function 980 // args[1]: number: break source position (within the function source) 981 // args[2]: number: break point object 982 RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) { 983 HandleScope scope(isolate); 984 DCHECK(args.length() == 3); 985 RUNTIME_ASSERT(isolate->debug()->is_active()); 986 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); 987 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]); 988 RUNTIME_ASSERT(source_position >= function->shared()->start_position() && 989 source_position <= function->shared()->end_position()); 990 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2); 991 992 // Set break point. 993 RUNTIME_ASSERT(isolate->debug()->SetBreakPoint( 994 function, break_point_object_arg, &source_position)); 995 996 return Smi::FromInt(source_position); 997 } 998 999 1000 // Changes the state of a break point in a script and returns source position 1001 // where break point was set. NOTE: Regarding performance see the NOTE for 1002 // GetScriptFromScriptData. 1003 // args[0]: script to set break point in 1004 // args[1]: number: break source position (within the script source) 1005 // args[2]: number, breakpoint position alignment 1006 // args[3]: number: break point object 1007 RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) { 1008 HandleScope scope(isolate); 1009 DCHECK(args.length() == 4); 1010 RUNTIME_ASSERT(isolate->debug()->is_active()); 1011 CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0); 1012 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]); 1013 RUNTIME_ASSERT(source_position >= 0); 1014 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]); 1015 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3); 1016 1017 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) { 1018 return isolate->ThrowIllegalOperation(); 1019 } 1020 BreakPositionAlignment alignment = 1021 static_cast<BreakPositionAlignment>(statement_aligned_code); 1022 1023 // Get the script from the script wrapper. 1024 RUNTIME_ASSERT(wrapper->value()->IsScript()); 1025 Handle<Script> script(Script::cast(wrapper->value())); 1026 1027 // Set break point. 1028 if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg, 1029 &source_position, alignment)) { 1030 return isolate->heap()->undefined_value(); 1031 } 1032 1033 return Smi::FromInt(source_position); 1034 } 1035 1036 1037 // Clear a break point 1038 // args[0]: number: break point object 1039 RUNTIME_FUNCTION(Runtime_ClearBreakPoint) { 1040 HandleScope scope(isolate); 1041 DCHECK(args.length() == 1); 1042 RUNTIME_ASSERT(isolate->debug()->is_active()); 1043 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0); 1044 1045 // Clear break point. 1046 isolate->debug()->ClearBreakPoint(break_point_object_arg); 1047 1048 return isolate->heap()->undefined_value(); 1049 } 1050 1051 1052 // Change the state of break on exceptions. 1053 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions. 1054 // args[1]: Boolean indicating on/off. 1055 RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) { 1056 HandleScope scope(isolate); 1057 DCHECK(args.length() == 2); 1058 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]); 1059 CONVERT_BOOLEAN_ARG_CHECKED(enable, 1); 1060 1061 // If the number doesn't match an enum value, the ChangeBreakOnException 1062 // function will default to affecting caught exceptions. 1063 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg); 1064 // Update break point state. 1065 isolate->debug()->ChangeBreakOnException(type, enable); 1066 return isolate->heap()->undefined_value(); 1067 } 1068 1069 1070 // Returns the state of break on exceptions 1071 // args[0]: boolean indicating uncaught exceptions 1072 RUNTIME_FUNCTION(Runtime_IsBreakOnException) { 1073 HandleScope scope(isolate); 1074 DCHECK(args.length() == 1); 1075 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]); 1076 1077 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg); 1078 bool result = isolate->debug()->IsBreakOnException(type); 1079 return Smi::FromInt(result); 1080 } 1081 1082 1083 // Prepare for stepping 1084 // args[0]: break id for checking execution state 1085 // args[1]: step action from the enumeration StepAction 1086 // args[2]: number of times to perform the step, for step out it is the number 1087 // of frames to step down. 1088 RUNTIME_FUNCTION(Runtime_PrepareStep) { 1089 HandleScope scope(isolate); 1090 DCHECK(args.length() == 2); 1091 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); 1092 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); 1093 1094 if (!args[1]->IsNumber()) { 1095 return isolate->Throw(isolate->heap()->illegal_argument_string()); 1096 } 1097 1098 // Get the step action and check validity. 1099 StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1])); 1100 if (step_action != StepIn && step_action != StepNext && 1101 step_action != StepOut && step_action != StepFrame) { 1102 return isolate->Throw(isolate->heap()->illegal_argument_string()); 1103 } 1104 1105 // Clear all current stepping setup. 1106 isolate->debug()->ClearStepping(); 1107 1108 // Prepare step. 1109 isolate->debug()->PrepareStep(static_cast<StepAction>(step_action)); 1110 return isolate->heap()->undefined_value(); 1111 } 1112 1113 1114 // Clear all stepping set by PrepareStep. 1115 RUNTIME_FUNCTION(Runtime_ClearStepping) { 1116 HandleScope scope(isolate); 1117 DCHECK(args.length() == 0); 1118 RUNTIME_ASSERT(isolate->debug()->is_active()); 1119 isolate->debug()->ClearStepping(); 1120 return isolate->heap()->undefined_value(); 1121 } 1122 1123 1124 RUNTIME_FUNCTION(Runtime_DebugEvaluate) { 1125 HandleScope scope(isolate); 1126 1127 // Check the execution state and decode arguments frame and source to be 1128 // evaluated. 1129 DCHECK(args.length() == 6); 1130 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); 1131 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); 1132 1133 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); 1134 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); 1135 CONVERT_ARG_HANDLE_CHECKED(String, source, 3); 1136 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4); 1137 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 5); 1138 1139 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); 1140 1141 RETURN_RESULT_OR_FAILURE( 1142 isolate, DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source, 1143 disable_break, context_extension)); 1144 } 1145 1146 1147 RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) { 1148 HandleScope scope(isolate); 1149 1150 // Check the execution state and decode arguments frame and source to be 1151 // evaluated. 1152 DCHECK(args.length() == 4); 1153 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); 1154 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); 1155 1156 CONVERT_ARG_HANDLE_CHECKED(String, source, 1); 1157 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2); 1158 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 3); 1159 1160 RETURN_RESULT_OR_FAILURE( 1161 isolate, 1162 DebugEvaluate::Global(isolate, source, disable_break, context_extension)); 1163 } 1164 1165 1166 RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) { 1167 HandleScope scope(isolate); 1168 DCHECK(args.length() == 0); 1169 RUNTIME_ASSERT(isolate->debug()->is_active()); 1170 1171 Handle<FixedArray> instances; 1172 { 1173 DebugScope debug_scope(isolate->debug()); 1174 if (debug_scope.failed()) { 1175 DCHECK(isolate->has_pending_exception()); 1176 return isolate->heap()->exception(); 1177 } 1178 // Fill the script objects. 1179 instances = isolate->debug()->GetLoadedScripts(); 1180 } 1181 1182 // Convert the script objects to proper JS objects. 1183 for (int i = 0; i < instances->length(); i++) { 1184 Handle<Script> script = Handle<Script>(Script::cast(instances->get(i))); 1185 // Get the script wrapper in a local handle before calling GetScriptWrapper, 1186 // because using 1187 // instances->set(i, *GetScriptWrapper(script)) 1188 // is unsafe as GetScriptWrapper might call GC and the C++ compiler might 1189 // already have dereferenced the instances handle. 1190 Handle<JSObject> wrapper = Script::GetWrapper(script); 1191 instances->set(i, *wrapper); 1192 } 1193 1194 // Return result as a JS array. 1195 return *isolate->factory()->NewJSArrayWithElements(instances); 1196 } 1197 1198 static bool HasInPrototypeChainIgnoringProxies(Isolate* isolate, 1199 JSObject* object, 1200 Object* proto) { 1201 PrototypeIterator iter(isolate, object, kStartAtReceiver); 1202 while (true) { 1203 iter.AdvanceIgnoringProxies(); 1204 if (iter.IsAtEnd()) return false; 1205 if (iter.GetCurrent() == proto) return true; 1206 } 1207 } 1208 1209 1210 // Scan the heap for objects with direct references to an object 1211 // args[0]: the object to find references to 1212 // args[1]: constructor function for instances to exclude (Mirror) 1213 // args[2]: the the maximum number of objects to return 1214 RUNTIME_FUNCTION(Runtime_DebugReferencedBy) { 1215 HandleScope scope(isolate); 1216 DCHECK(args.length() == 3); 1217 CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0); 1218 CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1); 1219 RUNTIME_ASSERT(filter->IsUndefined(isolate) || filter->IsJSObject()); 1220 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]); 1221 RUNTIME_ASSERT(max_references >= 0); 1222 1223 List<Handle<JSObject> > instances; 1224 Heap* heap = isolate->heap(); 1225 { 1226 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable); 1227 // Get the constructor function for context extension and arguments array. 1228 Object* arguments_fun = isolate->sloppy_arguments_map()->GetConstructor(); 1229 HeapObject* heap_obj; 1230 while ((heap_obj = iterator.next())) { 1231 if (!heap_obj->IsJSObject()) continue; 1232 JSObject* obj = JSObject::cast(heap_obj); 1233 if (obj->IsJSContextExtensionObject()) continue; 1234 if (obj->map()->GetConstructor() == arguments_fun) continue; 1235 if (!obj->ReferencesObject(*target)) continue; 1236 // Check filter if supplied. This is normally used to avoid 1237 // references from mirror objects. 1238 if (!filter->IsUndefined(isolate) && 1239 HasInPrototypeChainIgnoringProxies(isolate, obj, *filter)) { 1240 continue; 1241 } 1242 if (obj->IsJSGlobalObject()) { 1243 obj = JSGlobalObject::cast(obj)->global_proxy(); 1244 } 1245 instances.Add(Handle<JSObject>(obj)); 1246 if (instances.length() == max_references) break; 1247 } 1248 // Iterate the rest of the heap to satisfy HeapIterator constraints. 1249 while (iterator.next()) { 1250 } 1251 } 1252 1253 Handle<FixedArray> result; 1254 if (instances.length() == 1 && instances.last().is_identical_to(target)) { 1255 // Check for circular reference only. This can happen when the object is 1256 // only referenced from mirrors and has a circular reference in which case 1257 // the object is not really alive and would have been garbage collected if 1258 // not referenced from the mirror. 1259 result = isolate->factory()->empty_fixed_array(); 1260 } else { 1261 result = isolate->factory()->NewFixedArray(instances.length()); 1262 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]); 1263 } 1264 return *isolate->factory()->NewJSArrayWithElements(result); 1265 } 1266 1267 1268 // Scan the heap for objects constructed by a specific function. 1269 // args[0]: the constructor to find instances of 1270 // args[1]: the the maximum number of objects to return 1271 RUNTIME_FUNCTION(Runtime_DebugConstructedBy) { 1272 HandleScope scope(isolate); 1273 DCHECK(args.length() == 2); 1274 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0); 1275 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]); 1276 RUNTIME_ASSERT(max_references >= 0); 1277 1278 List<Handle<JSObject> > instances; 1279 Heap* heap = isolate->heap(); 1280 { 1281 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable); 1282 HeapObject* heap_obj; 1283 while ((heap_obj = iterator.next())) { 1284 if (!heap_obj->IsJSObject()) continue; 1285 JSObject* obj = JSObject::cast(heap_obj); 1286 if (obj->map()->GetConstructor() != *constructor) continue; 1287 instances.Add(Handle<JSObject>(obj)); 1288 if (instances.length() == max_references) break; 1289 } 1290 // Iterate the rest of the heap to satisfy HeapIterator constraints. 1291 while (iterator.next()) { 1292 } 1293 } 1294 1295 Handle<FixedArray> result = 1296 isolate->factory()->NewFixedArray(instances.length()); 1297 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]); 1298 return *isolate->factory()->NewJSArrayWithElements(result); 1299 } 1300 1301 1302 // Find the effective prototype object as returned by __proto__. 1303 // args[0]: the object to find the prototype for. 1304 RUNTIME_FUNCTION(Runtime_DebugGetPrototype) { 1305 HandleScope shs(isolate); 1306 DCHECK(args.length() == 1); 1307 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); 1308 // TODO(1543): Come up with a solution for clients to handle potential errors 1309 // thrown by an intermediate proxy. 1310 RETURN_RESULT_OR_FAILURE(isolate, JSReceiver::GetPrototype(isolate, obj)); 1311 } 1312 1313 1314 // Patches script source (should be called upon BeforeCompile event). 1315 RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) { 1316 HandleScope scope(isolate); 1317 DCHECK(args.length() == 2); 1318 1319 CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0); 1320 CONVERT_ARG_HANDLE_CHECKED(String, source, 1); 1321 1322 RUNTIME_ASSERT(script_wrapper->value()->IsScript()); 1323 Handle<Script> script(Script::cast(script_wrapper->value())); 1324 1325 int compilation_state = script->compilation_state(); 1326 RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL); 1327 script->set_source(*source); 1328 1329 return isolate->heap()->undefined_value(); 1330 } 1331 1332 1333 RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) { 1334 SealHandleScope shs(isolate); 1335 DCHECK_EQ(1, args.length()); 1336 1337 CONVERT_ARG_CHECKED(Object, f, 0); 1338 if (f->IsJSFunction()) { 1339 return JSFunction::cast(f)->shared()->inferred_name(); 1340 } 1341 return isolate->heap()->empty_string(); 1342 } 1343 1344 1345 RUNTIME_FUNCTION(Runtime_FunctionGetDebugName) { 1346 HandleScope scope(isolate); 1347 DCHECK_EQ(1, args.length()); 1348 1349 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); 1350 1351 if (function->IsJSBoundFunction()) { 1352 RETURN_RESULT_OR_FAILURE( 1353 isolate, JSBoundFunction::GetName( 1354 isolate, Handle<JSBoundFunction>::cast(function))); 1355 } else { 1356 return *JSFunction::GetDebugName(Handle<JSFunction>::cast(function)); 1357 } 1358 } 1359 1360 1361 // A testing entry. Returns statement position which is the closest to 1362 // source_position. 1363 RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource) { 1364 HandleScope scope(isolate); 1365 CHECK(isolate->debug()->live_edit_enabled()); 1366 DCHECK(args.length() == 2); 1367 RUNTIME_ASSERT(isolate->debug()->is_active()); 1368 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); 1369 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]); 1370 1371 Handle<Code> code(function->code(), isolate); 1372 1373 if (code->kind() != Code::FUNCTION && 1374 code->kind() != Code::OPTIMIZED_FUNCTION) { 1375 return isolate->heap()->undefined_value(); 1376 } 1377 1378 RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION)); 1379 int closest_pc = 0; 1380 int distance = kMaxInt; 1381 while (!it.done()) { 1382 int statement_position = static_cast<int>(it.rinfo()->data()); 1383 // Check if this break point is closer that what was previously found. 1384 if (source_position <= statement_position && 1385 statement_position - source_position < distance) { 1386 closest_pc = 1387 static_cast<int>(it.rinfo()->pc() - code->instruction_start()); 1388 distance = statement_position - source_position; 1389 // Check whether we can't get any closer. 1390 if (distance == 0) break; 1391 } 1392 it.next(); 1393 } 1394 1395 return Smi::FromInt(closest_pc); 1396 } 1397 1398 1399 // Calls specified function with or without entering the debugger. 1400 // This is used in unit tests to run code as if debugger is entered or simply 1401 // to have a stack with C++ frame in the middle. 1402 RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext) { 1403 HandleScope scope(isolate); 1404 DCHECK(args.length() == 1); 1405 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); 1406 1407 DebugScope debug_scope(isolate->debug()); 1408 if (debug_scope.failed()) { 1409 DCHECK(isolate->has_pending_exception()); 1410 return isolate->heap()->exception(); 1411 } 1412 1413 RETURN_RESULT_OR_FAILURE( 1414 isolate, Execution::Call(isolate, function, 1415 handle(function->global_proxy()), 0, NULL)); 1416 } 1417 1418 1419 RUNTIME_FUNCTION(Runtime_GetDebugContext) { 1420 HandleScope scope(isolate); 1421 DCHECK(args.length() == 0); 1422 Handle<Context> context; 1423 { 1424 DebugScope debug_scope(isolate->debug()); 1425 if (debug_scope.failed()) { 1426 DCHECK(isolate->has_pending_exception()); 1427 return isolate->heap()->exception(); 1428 } 1429 context = isolate->debug()->GetDebugContext(); 1430 } 1431 if (context.is_null()) return isolate->heap()->undefined_value(); 1432 context->set_security_token(isolate->native_context()->security_token()); 1433 return context->global_proxy(); 1434 } 1435 1436 1437 // Performs a GC. 1438 // Presently, it only does a full GC. 1439 RUNTIME_FUNCTION(Runtime_CollectGarbage) { 1440 SealHandleScope shs(isolate); 1441 DCHECK(args.length() == 1); 1442 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage"); 1443 return isolate->heap()->undefined_value(); 1444 } 1445 1446 1447 // Gets the current heap usage. 1448 RUNTIME_FUNCTION(Runtime_GetHeapUsage) { 1449 SealHandleScope shs(isolate); 1450 DCHECK(args.length() == 0); 1451 int usage = static_cast<int>(isolate->heap()->SizeOfObjects()); 1452 if (!Smi::IsValid(usage)) { 1453 return *isolate->factory()->NewNumberFromInt(usage); 1454 } 1455 return Smi::FromInt(usage); 1456 } 1457 1458 1459 // Finds the script object from the script data. NOTE: This operation uses 1460 // heap traversal to find the function generated for the source position 1461 // for the requested break point. For lazily compiled functions several heap 1462 // traversals might be required rendering this operation as a rather slow 1463 // operation. However for setting break points which is normally done through 1464 // some kind of user interaction the performance is not crucial. 1465 RUNTIME_FUNCTION(Runtime_GetScript) { 1466 HandleScope scope(isolate); 1467 DCHECK(args.length() == 1); 1468 CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0); 1469 1470 Handle<Script> found; 1471 { 1472 Script::Iterator iterator(isolate); 1473 Script* script = NULL; 1474 while ((script = iterator.Next()) != NULL) { 1475 if (!script->name()->IsString()) continue; 1476 String* name = String::cast(script->name()); 1477 if (name->Equals(*script_name)) { 1478 found = Handle<Script>(script, isolate); 1479 break; 1480 } 1481 } 1482 } 1483 1484 if (found.is_null()) return isolate->heap()->undefined_value(); 1485 return *Script::GetWrapper(found); 1486 } 1487 1488 RUNTIME_FUNCTION(Runtime_ScriptLineCount) { 1489 HandleScope scope(isolate); 1490 DCHECK(args.length() == 1); 1491 CONVERT_ARG_CHECKED(JSValue, script, 0); 1492 1493 RUNTIME_ASSERT(script->value()->IsScript()); 1494 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value())); 1495 1496 Script::InitLineEnds(script_handle); 1497 1498 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends()); 1499 return Smi::FromInt(line_ends_array->length()); 1500 } 1501 1502 RUNTIME_FUNCTION(Runtime_ScriptLineStartPosition) { 1503 HandleScope scope(isolate); 1504 DCHECK(args.length() == 2); 1505 CONVERT_ARG_CHECKED(JSValue, script, 0); 1506 CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]); 1507 1508 RUNTIME_ASSERT(script->value()->IsScript()); 1509 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value())); 1510 1511 Script::InitLineEnds(script_handle); 1512 1513 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends()); 1514 const int line_count = line_ends_array->length(); 1515 1516 // If line == line_count, we return the first position beyond the last line. 1517 if (line < 0 || line > line_count) { 1518 return Smi::FromInt(-1); 1519 } else if (line == 0) { 1520 return Smi::FromInt(0); 1521 } else { 1522 DCHECK(0 < line && line <= line_count); 1523 const int pos = Smi::cast(line_ends_array->get(line - 1))->value() + 1; 1524 return Smi::FromInt(pos); 1525 } 1526 } 1527 1528 RUNTIME_FUNCTION(Runtime_ScriptLineEndPosition) { 1529 HandleScope scope(isolate); 1530 DCHECK(args.length() == 2); 1531 CONVERT_ARG_CHECKED(JSValue, script, 0); 1532 CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]); 1533 1534 RUNTIME_ASSERT(script->value()->IsScript()); 1535 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value())); 1536 1537 Script::InitLineEnds(script_handle); 1538 1539 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends()); 1540 const int line_count = line_ends_array->length(); 1541 1542 if (line < 0 || line >= line_count) { 1543 return Smi::FromInt(-1); 1544 } else { 1545 return Smi::cast(line_ends_array->get(line)); 1546 } 1547 } 1548 1549 static Handle<Object> GetJSPositionInfo(Handle<Script> script, int position, 1550 Script::OffsetFlag offset_flag, 1551 Isolate* isolate) { 1552 Script::PositionInfo info; 1553 if (!script->GetPositionInfo(position, &info, offset_flag)) { 1554 return handle(isolate->heap()->null_value(), isolate); 1555 } 1556 1557 Handle<String> source = handle(String::cast(script->source()), isolate); 1558 Handle<String> sourceText = 1559 isolate->factory()->NewSubString(source, info.line_start, info.line_end); 1560 1561 Handle<JSObject> jsinfo = 1562 isolate->factory()->NewJSObject(isolate->object_function()); 1563 1564 JSObject::AddProperty(jsinfo, isolate->factory()->script_string(), script, 1565 NONE); 1566 JSObject::AddProperty(jsinfo, isolate->factory()->position_string(), 1567 handle(Smi::FromInt(position), isolate), NONE); 1568 JSObject::AddProperty(jsinfo, isolate->factory()->line_string(), 1569 handle(Smi::FromInt(info.line), isolate), NONE); 1570 JSObject::AddProperty(jsinfo, isolate->factory()->column_string(), 1571 handle(Smi::FromInt(info.column), isolate), NONE); 1572 JSObject::AddProperty(jsinfo, isolate->factory()->sourceText_string(), 1573 sourceText, NONE); 1574 1575 return jsinfo; 1576 } 1577 1578 // Get information on a specific source line and column possibly offset by a 1579 // fixed source position. This function is used to find a source position from 1580 // a line and column position. The fixed source position offset is typically 1581 // used to find a source position in a function based on a line and column in 1582 // the source for the function alone. The offset passed will then be the 1583 // start position of the source for the function within the full script source. 1584 // Note that incoming line and column parameters may be undefined, and are 1585 // assumed to be passed *with* offsets. 1586 RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine) { 1587 HandleScope scope(isolate); 1588 DCHECK(args.length() == 4); 1589 CONVERT_ARG_CHECKED(JSValue, script, 0); 1590 1591 RUNTIME_ASSERT(script->value()->IsScript()); 1592 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value())); 1593 1594 // Line and column are possibly undefined and we need to handle these cases, 1595 // additionally subtracting corresponding offsets. 1596 1597 int32_t line; 1598 if (args[1]->IsNull(isolate) || args[1]->IsUndefined(isolate)) { 1599 line = 0; 1600 } else { 1601 RUNTIME_ASSERT(args[1]->IsNumber()); 1602 line = NumberToInt32(args[1]) - script_handle->line_offset(); 1603 } 1604 1605 int32_t column; 1606 if (args[2]->IsNull(isolate) || args[2]->IsUndefined(isolate)) { 1607 column = 0; 1608 } else { 1609 RUNTIME_ASSERT(args[2]->IsNumber()); 1610 column = NumberToInt32(args[2]); 1611 if (line == 0) column -= script_handle->column_offset(); 1612 } 1613 1614 CONVERT_NUMBER_CHECKED(int32_t, offset_position, Int32, args[3]); 1615 1616 if (line < 0 || column < 0 || offset_position < 0) { 1617 return isolate->heap()->null_value(); 1618 } 1619 1620 Script::InitLineEnds(script_handle); 1621 1622 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends()); 1623 const int line_count = line_ends_array->length(); 1624 1625 int position; 1626 if (line == 0) { 1627 position = offset_position + column; 1628 } else { 1629 Script::PositionInfo info; 1630 if (!script_handle->GetPositionInfo(offset_position, &info, 1631 Script::NO_OFFSET) || 1632 info.line + line >= line_count) { 1633 return isolate->heap()->null_value(); 1634 } 1635 1636 const int offset_line = info.line + line; 1637 const int offset_line_position = 1638 (offset_line == 0) 1639 ? 0 1640 : Smi::cast(line_ends_array->get(offset_line - 1))->value() + 1; 1641 position = offset_line_position + column; 1642 } 1643 1644 return *GetJSPositionInfo(script_handle, position, Script::NO_OFFSET, 1645 isolate); 1646 } 1647 1648 RUNTIME_FUNCTION(Runtime_ScriptPositionInfo) { 1649 HandleScope scope(isolate); 1650 DCHECK(args.length() == 3); 1651 CONVERT_ARG_CHECKED(JSValue, script, 0); 1652 CONVERT_NUMBER_CHECKED(int32_t, position, Int32, args[1]); 1653 CONVERT_BOOLEAN_ARG_CHECKED(with_offset, 2); 1654 1655 RUNTIME_ASSERT(script->value()->IsScript()); 1656 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value())); 1657 1658 const Script::OffsetFlag offset_flag = 1659 with_offset ? Script::WITH_OFFSET : Script::NO_OFFSET; 1660 return *GetJSPositionInfo(script_handle, position, offset_flag, isolate); 1661 } 1662 1663 // Returns the given line as a string, or null if line is out of bounds. 1664 // The parameter line is expected to include the script's line offset. 1665 RUNTIME_FUNCTION(Runtime_ScriptSourceLine) { 1666 HandleScope scope(isolate); 1667 DCHECK(args.length() == 2); 1668 CONVERT_ARG_CHECKED(JSValue, script, 0); 1669 CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]); 1670 1671 RUNTIME_ASSERT(script->value()->IsScript()); 1672 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value())); 1673 1674 Script::InitLineEnds(script_handle); 1675 1676 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends()); 1677 const int line_count = line_ends_array->length(); 1678 1679 line -= script_handle->line_offset(); 1680 if (line < 0 || line_count <= line) { 1681 return isolate->heap()->null_value(); 1682 } 1683 1684 const int start = 1685 (line == 0) ? 0 : Smi::cast(line_ends_array->get(line - 1))->value() + 1; 1686 const int end = Smi::cast(line_ends_array->get(line))->value(); 1687 1688 Handle<String> source = 1689 handle(String::cast(script_handle->source()), isolate); 1690 Handle<String> str = isolate->factory()->NewSubString(source, start, end); 1691 1692 return *str; 1693 } 1694 1695 // Set one shot breakpoints for the callback function that is passed to a 1696 // built-in function such as Array.forEach to enable stepping into the callback, 1697 // if we are indeed stepping and the callback is subject to debugging. 1698 RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) { 1699 HandleScope scope(isolate); 1700 DCHECK_EQ(1, args.length()); 1701 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); 1702 isolate->debug()->PrepareStepIn(fun); 1703 return isolate->heap()->undefined_value(); 1704 } 1705 1706 // Set one shot breakpoints for the suspended generator object. 1707 RUNTIME_FUNCTION(Runtime_DebugPrepareStepInSuspendedGenerator) { 1708 HandleScope scope(isolate); 1709 DCHECK_EQ(0, args.length()); 1710 isolate->debug()->PrepareStepInSuspendedGenerator(); 1711 return isolate->heap()->undefined_value(); 1712 } 1713 1714 RUNTIME_FUNCTION(Runtime_DebugRecordAsyncFunction) { 1715 HandleScope scope(isolate); 1716 DCHECK_EQ(1, args.length()); 1717 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); 1718 CHECK(isolate->debug()->last_step_action() >= StepNext); 1719 isolate->debug()->RecordAsyncFunction(generator); 1720 return isolate->heap()->undefined_value(); 1721 } 1722 1723 RUNTIME_FUNCTION(Runtime_DebugPushPromise) { 1724 DCHECK(args.length() == 2); 1725 HandleScope scope(isolate); 1726 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); 1727 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1); 1728 isolate->PushPromise(promise, function); 1729 return isolate->heap()->undefined_value(); 1730 } 1731 1732 1733 RUNTIME_FUNCTION(Runtime_DebugPopPromise) { 1734 DCHECK(args.length() == 0); 1735 SealHandleScope shs(isolate); 1736 isolate->PopPromise(); 1737 return isolate->heap()->undefined_value(); 1738 } 1739 1740 1741 RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent) { 1742 DCHECK(args.length() == 1); 1743 HandleScope scope(isolate); 1744 CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0); 1745 isolate->debug()->OnAsyncTaskEvent(data); 1746 return isolate->heap()->undefined_value(); 1747 } 1748 1749 1750 RUNTIME_FUNCTION(Runtime_DebugIsActive) { 1751 SealHandleScope shs(isolate); 1752 return Smi::FromInt(isolate->debug()->is_active()); 1753 } 1754 1755 1756 RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) { 1757 UNIMPLEMENTED(); 1758 return NULL; 1759 } 1760 } // namespace internal 1761 } // namespace v8 1762