1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/debug/debug-evaluate.h" 6 7 #include "src/accessors.h" 8 #include "src/assembler-inl.h" 9 #include "src/compiler.h" 10 #include "src/contexts.h" 11 #include "src/debug/debug-frames.h" 12 #include "src/debug/debug-scopes.h" 13 #include "src/debug/debug.h" 14 #include "src/frames-inl.h" 15 #include "src/globals.h" 16 #include "src/interpreter/bytecode-array-iterator.h" 17 #include "src/interpreter/bytecodes.h" 18 #include "src/isolate-inl.h" 19 #include "src/objects/api-callbacks.h" 20 #include "src/snapshot/snapshot.h" 21 22 namespace v8 { 23 namespace internal { 24 25 MaybeHandle<Object> DebugEvaluate::Global(Isolate* isolate, 26 Handle<String> source, 27 bool throw_on_side_effect) { 28 // Disable breaks in side-effect free mode. 29 DisableBreak disable_break_scope(isolate->debug(), throw_on_side_effect); 30 31 Handle<Context> context = isolate->native_context(); 32 ScriptOriginOptions origin_options(false, true); 33 MaybeHandle<SharedFunctionInfo> maybe_function_info = 34 Compiler::GetSharedFunctionInfoForScript( 35 isolate, source, 36 Compiler::ScriptDetails(isolate->factory()->empty_string()), 37 origin_options, nullptr, nullptr, ScriptCompiler::kNoCompileOptions, 38 ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE); 39 40 Handle<SharedFunctionInfo> shared_info; 41 if (!maybe_function_info.ToHandle(&shared_info)) return MaybeHandle<Object>(); 42 43 Handle<JSFunction> fun = 44 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared_info, 45 context); 46 if (throw_on_side_effect) isolate->debug()->StartSideEffectCheckMode(); 47 MaybeHandle<Object> result = Execution::Call( 48 isolate, fun, Handle<JSObject>(context->global_proxy(), isolate), 0, 49 nullptr); 50 if (throw_on_side_effect) isolate->debug()->StopSideEffectCheckMode(); 51 return result; 52 } 53 54 MaybeHandle<Object> DebugEvaluate::Local(Isolate* isolate, 55 StackFrame::Id frame_id, 56 int inlined_jsframe_index, 57 Handle<String> source, 58 bool throw_on_side_effect) { 59 // Handle the processing of break. 60 DisableBreak disable_break_scope(isolate->debug()); 61 62 // Get the frame where the debugging is performed. 63 StackTraceFrameIterator it(isolate, frame_id); 64 if (!it.is_javascript()) return isolate->factory()->undefined_value(); 65 JavaScriptFrame* frame = it.javascript_frame(); 66 67 // This is not a lot different than DebugEvaluate::Global, except that 68 // variables accessible by the function we are evaluating from are 69 // materialized and included on top of the native context. Changes to 70 // the materialized object are written back afterwards. 71 // Note that the native context is taken from the original context chain, 72 // which may not be the current native context of the isolate. 73 ContextBuilder context_builder(isolate, frame, inlined_jsframe_index); 74 if (isolate->has_pending_exception()) return MaybeHandle<Object>(); 75 76 Handle<Context> context = context_builder.evaluation_context(); 77 Handle<JSObject> receiver(context->global_proxy(), isolate); 78 MaybeHandle<Object> maybe_result = 79 Evaluate(isolate, context_builder.outer_info(), context, receiver, source, 80 throw_on_side_effect); 81 if (!maybe_result.is_null()) context_builder.UpdateValues(); 82 return maybe_result; 83 } 84 85 MaybeHandle<Object> DebugEvaluate::WithTopmostArguments(Isolate* isolate, 86 Handle<String> source) { 87 // Handle the processing of break. 88 DisableBreak disable_break_scope(isolate->debug()); 89 Factory* factory = isolate->factory(); 90 JavaScriptFrameIterator it(isolate); 91 92 // Get context and receiver. 93 Handle<Context> native_context( 94 Context::cast(it.frame()->context())->native_context(), isolate); 95 96 // Materialize arguments as property on an extension object. 97 Handle<JSObject> materialized = factory->NewJSObjectWithNullProto(); 98 Handle<String> arguments_str = factory->arguments_string(); 99 JSObject::SetOwnPropertyIgnoreAttributes( 100 materialized, arguments_str, 101 Accessors::FunctionGetArguments(it.frame(), 0), NONE) 102 .Check(); 103 104 // Materialize receiver. 105 Handle<String> this_str = factory->this_string(); 106 JSObject::SetOwnPropertyIgnoreAttributes( 107 materialized, this_str, Handle<Object>(it.frame()->receiver(), isolate), 108 NONE) 109 .Check(); 110 111 // Use extension object in a debug-evaluate scope. 112 Handle<ScopeInfo> scope_info = 113 ScopeInfo::CreateForWithScope(isolate, Handle<ScopeInfo>::null()); 114 scope_info->SetIsDebugEvaluateScope(); 115 Handle<Context> evaluation_context = 116 factory->NewDebugEvaluateContext(native_context, scope_info, materialized, 117 Handle<Context>(), Handle<StringSet>()); 118 Handle<SharedFunctionInfo> outer_info( 119 native_context->empty_function()->shared(), isolate); 120 Handle<JSObject> receiver(native_context->global_proxy(), isolate); 121 const bool throw_on_side_effect = false; 122 MaybeHandle<Object> maybe_result = 123 Evaluate(isolate, outer_info, evaluation_context, receiver, source, 124 throw_on_side_effect); 125 return maybe_result; 126 } 127 128 // Compile and evaluate source for the given context. 129 MaybeHandle<Object> DebugEvaluate::Evaluate( 130 Isolate* isolate, Handle<SharedFunctionInfo> outer_info, 131 Handle<Context> context, Handle<Object> receiver, Handle<String> source, 132 bool throw_on_side_effect) { 133 Handle<JSFunction> eval_fun; 134 ASSIGN_RETURN_ON_EXCEPTION( 135 isolate, eval_fun, 136 Compiler::GetFunctionFromEval(source, outer_info, context, 137 LanguageMode::kSloppy, NO_PARSE_RESTRICTION, 138 kNoSourcePosition, kNoSourcePosition, 139 kNoSourcePosition), 140 Object); 141 142 Handle<Object> result; 143 bool sucess = false; 144 if (throw_on_side_effect) isolate->debug()->StartSideEffectCheckMode(); 145 sucess = Execution::Call(isolate, eval_fun, receiver, 0, nullptr) 146 .ToHandle(&result); 147 if (throw_on_side_effect) isolate->debug()->StopSideEffectCheckMode(); 148 if (!sucess) { 149 DCHECK(isolate->has_pending_exception()); 150 return MaybeHandle<Object>(); 151 } 152 153 // Skip the global proxy as it has no properties and always delegates to the 154 // real global object. 155 if (result->IsJSGlobalProxy()) { 156 PrototypeIterator iter(isolate, Handle<JSGlobalProxy>::cast(result)); 157 // TODO(verwaest): This will crash when the global proxy is detached. 158 result = PrototypeIterator::GetCurrent<JSObject>(iter); 159 } 160 161 return result; 162 } 163 164 Handle<SharedFunctionInfo> DebugEvaluate::ContextBuilder::outer_info() const { 165 return handle(frame_inspector_.GetFunction()->shared(), isolate_); 166 } 167 168 DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate, 169 JavaScriptFrame* frame, 170 int inlined_jsframe_index) 171 : isolate_(isolate), 172 frame_inspector_(frame, inlined_jsframe_index, isolate), 173 scope_iterator_(isolate, &frame_inspector_, 174 ScopeIterator::COLLECT_NON_LOCALS) { 175 Handle<Context> outer_context(frame_inspector_.GetFunction()->context(), 176 isolate); 177 evaluation_context_ = outer_context; 178 Factory* factory = isolate->factory(); 179 180 if (scope_iterator_.Done()) return; 181 182 // To evaluate as if we were running eval at the point of the debug break, 183 // we reconstruct the context chain as follows: 184 // - To make stack-allocated variables visible, we materialize them and 185 // use a debug-evaluate context to wrap both the materialized object and 186 // the original context. 187 // - We use the original context chain from the function context to the 188 // native context. 189 // - Between the function scope and the native context, we only resolve 190 // variable names that the current function already uses. Only for these 191 // names we can be sure that they will be correctly resolved. For the 192 // rest, we only resolve to with, script, and native contexts. We use a 193 // whitelist to implement that. 194 // Context::Lookup has special handling for debug-evaluate contexts: 195 // - Look up in the materialized stack variables. 196 // - Look up in the original context. 197 // - Check the whitelist to find out whether to skip contexts during lookup. 198 for (; scope_iterator_.InInnerScope(); scope_iterator_.Next()) { 199 ScopeIterator::ScopeType scope_type = scope_iterator_.Type(); 200 if (scope_type == ScopeIterator::ScopeTypeScript) break; 201 ContextChainElement context_chain_element; 202 if (scope_type == ScopeIterator::ScopeTypeLocal || 203 scope_iterator_.DeclaresLocals(ScopeIterator::Mode::STACK)) { 204 context_chain_element.materialized_object = 205 scope_iterator_.ScopeObject(ScopeIterator::Mode::STACK); 206 } 207 if (scope_iterator_.HasContext()) { 208 context_chain_element.wrapped_context = scope_iterator_.CurrentContext(); 209 } 210 if (scope_type == ScopeIterator::ScopeTypeLocal) { 211 context_chain_element.whitelist = scope_iterator_.GetNonLocals(); 212 } 213 context_chain_.push_back(context_chain_element); 214 } 215 216 Handle<ScopeInfo> scope_info = 217 evaluation_context_->IsNativeContext() 218 ? Handle<ScopeInfo>::null() 219 : handle(evaluation_context_->scope_info(), isolate); 220 for (auto rit = context_chain_.rbegin(); rit != context_chain_.rend(); 221 rit++) { 222 ContextChainElement element = *rit; 223 scope_info = ScopeInfo::CreateForWithScope(isolate, scope_info); 224 scope_info->SetIsDebugEvaluateScope(); 225 evaluation_context_ = factory->NewDebugEvaluateContext( 226 evaluation_context_, scope_info, element.materialized_object, 227 element.wrapped_context, element.whitelist); 228 } 229 } 230 231 232 void DebugEvaluate::ContextBuilder::UpdateValues() { 233 scope_iterator_.Restart(); 234 for (ContextChainElement& element : context_chain_) { 235 if (!element.materialized_object.is_null()) { 236 Handle<FixedArray> keys = 237 KeyAccumulator::GetKeys(element.materialized_object, 238 KeyCollectionMode::kOwnOnly, 239 ENUMERABLE_STRINGS) 240 .ToHandleChecked(); 241 242 for (int i = 0; i < keys->length(); i++) { 243 DCHECK(keys->get(i)->IsString()); 244 Handle<String> key(String::cast(keys->get(i)), isolate_); 245 Handle<Object> value = 246 JSReceiver::GetDataProperty(element.materialized_object, key); 247 scope_iterator_.SetVariableValue(key, value); 248 } 249 } 250 scope_iterator_.Next(); 251 } 252 } 253 254 namespace { 255 256 bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) { 257 // Use macro to include both inlined and non-inlined version of an intrinsic. 258 #define INTRINSIC_WHITELIST(V) \ 259 /* Conversions */ \ 260 V(NumberToString) \ 261 V(ToBigInt) \ 262 V(ToInteger) \ 263 V(ToLength) \ 264 V(ToNumber) \ 265 V(ToObject) \ 266 V(ToString) \ 267 /* Type checks */ \ 268 V(IsArray) \ 269 V(IsDate) \ 270 V(IsFunction) \ 271 V(IsJSProxy) \ 272 V(IsJSReceiver) \ 273 V(IsRegExp) \ 274 V(IsSmi) \ 275 V(IsTypedArray) \ 276 /* Loads */ \ 277 V(LoadLookupSlotForCall) \ 278 V(GetProperty) \ 279 /* Arrays */ \ 280 V(ArraySpeciesConstructor) \ 281 V(EstimateNumberOfElements) \ 282 V(GetArrayKeys) \ 283 V(HasComplexElements) \ 284 V(HasFastPackedElements) \ 285 V(NewArray) \ 286 V(NormalizeElements) \ 287 V(PrepareElementsForSort) \ 288 V(TrySliceSimpleNonFastElements) \ 289 V(TypedArrayGetBuffer) \ 290 /* Errors */ \ 291 V(NewTypeError) \ 292 V(ReThrow) \ 293 V(ThrowCalledNonCallable) \ 294 V(ThrowInvalidStringLength) \ 295 V(ThrowIteratorResultNotAnObject) \ 296 V(ThrowReferenceError) \ 297 V(ThrowSymbolIteratorInvalid) \ 298 /* Strings */ \ 299 V(RegExpInternalReplace) \ 300 V(StringIncludes) \ 301 V(StringIndexOf) \ 302 V(StringReplaceOneCharWithString) \ 303 V(StringSubstring) \ 304 V(StringToNumber) \ 305 V(StringTrim) \ 306 /* BigInts */ \ 307 V(BigIntEqualToBigInt) \ 308 V(BigIntToBoolean) \ 309 V(BigIntToNumber) \ 310 /* Literals */ \ 311 V(CreateArrayLiteral) \ 312 V(CreateArrayLiteralWithoutAllocationSite) \ 313 V(CreateObjectLiteral) \ 314 V(CreateObjectLiteralWithoutAllocationSite) \ 315 V(CreateRegExpLiteral) \ 316 /* Called from builtins */ \ 317 V(AllocateInNewSpace) \ 318 V(AllocateInTargetSpace) \ 319 V(AllocateSeqOneByteString) \ 320 V(AllocateSeqTwoByteString) \ 321 V(ArrayIncludes_Slow) \ 322 V(ArrayIndexOf) \ 323 V(ArrayIsArray) \ 324 V(ClassOf) \ 325 V(GenerateRandomNumbers) \ 326 V(GetFunctionName) \ 327 V(GetOwnPropertyDescriptor) \ 328 V(GlobalPrint) \ 329 V(HasProperty) \ 330 V(ObjectCreate) \ 331 V(ObjectEntries) \ 332 V(ObjectEntriesSkipFastPath) \ 333 V(ObjectHasOwnProperty) \ 334 V(ObjectValues) \ 335 V(ObjectValuesSkipFastPath) \ 336 V(ObjectGetOwnPropertyNames) \ 337 V(ObjectGetOwnPropertyNamesTryFast) \ 338 V(RegExpInitializeAndCompile) \ 339 V(StackGuard) \ 340 V(StringAdd) \ 341 V(StringCharCodeAt) \ 342 V(StringEqual) \ 343 V(StringIndexOfUnchecked) \ 344 V(StringParseFloat) \ 345 V(StringParseInt) \ 346 V(SymbolDescriptiveString) \ 347 V(ThrowRangeError) \ 348 V(ThrowTypeError) \ 349 V(ToName) \ 350 V(TransitionElementsKind) \ 351 /* Misc. */ \ 352 V(Call) \ 353 V(CompleteInobjectSlackTrackingForMap) \ 354 V(HasInPrototypeChain) \ 355 V(MaxSmi) \ 356 V(NewObject) \ 357 V(SmiLexicographicCompare) \ 358 V(StringMaxLength) \ 359 V(StringToArray) \ 360 /* Test */ \ 361 V(GetOptimizationStatus) \ 362 V(OptimizeFunctionOnNextCall) \ 363 V(OptimizeOsr) \ 364 V(UnblockConcurrentRecompilation) 365 366 #define CASE(Name) \ 367 case Runtime::k##Name: \ 368 case Runtime::kInline##Name: 369 370 switch (id) { 371 INTRINSIC_WHITELIST(CASE) 372 return true; 373 default: 374 if (FLAG_trace_side_effect_free_debug_evaluate) { 375 PrintF("[debug-evaluate] intrinsic %s may cause side effect.\n", 376 Runtime::FunctionForId(id)->name); 377 } 378 return false; 379 } 380 381 #undef CASE 382 #undef INTRINSIC_WHITELIST 383 } 384 385 #ifdef DEBUG 386 bool BuiltinToIntrinsicHasNoSideEffect(Builtins::Name builtin_id, 387 Runtime::FunctionId intrinsic_id) { 388 // First check the intrinsic whitelist. 389 if (IntrinsicHasNoSideEffect(intrinsic_id)) return true; 390 391 // Whitelist intrinsics called from specific builtins. 392 #define BUILTIN_INTRINSIC_WHITELIST(V, W) \ 393 /* Arrays */ \ 394 V(Builtins::kArrayFilter, W(CreateDataProperty)) \ 395 V(Builtins::kArrayMap, W(CreateDataProperty)) \ 396 V(Builtins::kArrayPrototypeSlice, W(CreateDataProperty) W(SetProperty)) \ 397 /* TypedArrays */ \ 398 V(Builtins::kTypedArrayConstructor, \ 399 W(TypedArrayCopyElements) W(ThrowInvalidTypedArrayAlignment)) \ 400 V(Builtins::kTypedArrayPrototypeFilter, W(TypedArrayCopyElements)) \ 401 V(Builtins::kTypedArrayPrototypeMap, W(SetProperty)) 402 403 #define CASE(Builtin, ...) \ 404 case Builtin: \ 405 return (__VA_ARGS__ false); 406 407 #define MATCH(Intrinsic) \ 408 intrinsic_id == Runtime::k##Intrinsic || \ 409 intrinsic_id == Runtime::kInline##Intrinsic || 410 411 switch (builtin_id) { 412 BUILTIN_INTRINSIC_WHITELIST(CASE, MATCH) 413 default: 414 return false; 415 } 416 417 #undef MATCH 418 #undef CASE 419 #undef BUILTIN_INTRINSIC_WHITELIST 420 } 421 #endif // DEBUG 422 423 bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) { 424 typedef interpreter::Bytecode Bytecode; 425 typedef interpreter::Bytecodes Bytecodes; 426 if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) return true; 427 if (Bytecodes::IsCallOrConstruct(bytecode)) return true; 428 if (Bytecodes::IsJumpIfToBoolean(bytecode)) return true; 429 if (Bytecodes::IsPrefixScalingBytecode(bytecode)) return true; 430 switch (bytecode) { 431 // Whitelist for bytecodes. 432 // Loads. 433 case Bytecode::kLdaLookupSlot: 434 case Bytecode::kLdaGlobal: 435 case Bytecode::kLdaNamedProperty: 436 case Bytecode::kLdaKeyedProperty: 437 case Bytecode::kLdaGlobalInsideTypeof: 438 case Bytecode::kLdaLookupSlotInsideTypeof: 439 // Arithmetics. 440 case Bytecode::kAdd: 441 case Bytecode::kAddSmi: 442 case Bytecode::kSub: 443 case Bytecode::kSubSmi: 444 case Bytecode::kMul: 445 case Bytecode::kMulSmi: 446 case Bytecode::kDiv: 447 case Bytecode::kDivSmi: 448 case Bytecode::kMod: 449 case Bytecode::kModSmi: 450 case Bytecode::kExp: 451 case Bytecode::kExpSmi: 452 case Bytecode::kNegate: 453 case Bytecode::kBitwiseAnd: 454 case Bytecode::kBitwiseAndSmi: 455 case Bytecode::kBitwiseNot: 456 case Bytecode::kBitwiseOr: 457 case Bytecode::kBitwiseOrSmi: 458 case Bytecode::kBitwiseXor: 459 case Bytecode::kBitwiseXorSmi: 460 case Bytecode::kShiftLeft: 461 case Bytecode::kShiftLeftSmi: 462 case Bytecode::kShiftRight: 463 case Bytecode::kShiftRightSmi: 464 case Bytecode::kShiftRightLogical: 465 case Bytecode::kShiftRightLogicalSmi: 466 case Bytecode::kInc: 467 case Bytecode::kDec: 468 case Bytecode::kLogicalNot: 469 case Bytecode::kToBooleanLogicalNot: 470 case Bytecode::kTypeOf: 471 // Contexts. 472 case Bytecode::kCreateBlockContext: 473 case Bytecode::kCreateCatchContext: 474 case Bytecode::kCreateFunctionContext: 475 case Bytecode::kCreateEvalContext: 476 case Bytecode::kCreateWithContext: 477 // Literals. 478 case Bytecode::kCreateArrayLiteral: 479 case Bytecode::kCreateEmptyArrayLiteral: 480 case Bytecode::kCreateObjectLiteral: 481 case Bytecode::kCreateEmptyObjectLiteral: 482 case Bytecode::kCreateRegExpLiteral: 483 // Allocations. 484 case Bytecode::kCreateClosure: 485 case Bytecode::kCreateUnmappedArguments: 486 case Bytecode::kCreateRestParameter: 487 // Comparisons. 488 case Bytecode::kTestEqual: 489 case Bytecode::kTestEqualStrict: 490 case Bytecode::kTestLessThan: 491 case Bytecode::kTestLessThanOrEqual: 492 case Bytecode::kTestGreaterThan: 493 case Bytecode::kTestGreaterThanOrEqual: 494 case Bytecode::kTestInstanceOf: 495 case Bytecode::kTestIn: 496 case Bytecode::kTestReferenceEqual: 497 case Bytecode::kTestUndetectable: 498 case Bytecode::kTestTypeOf: 499 case Bytecode::kTestUndefined: 500 case Bytecode::kTestNull: 501 // Conversions. 502 case Bytecode::kToObject: 503 case Bytecode::kToName: 504 case Bytecode::kToNumber: 505 case Bytecode::kToNumeric: 506 case Bytecode::kToString: 507 // Misc. 508 case Bytecode::kForInEnumerate: 509 case Bytecode::kForInPrepare: 510 case Bytecode::kForInContinue: 511 case Bytecode::kForInNext: 512 case Bytecode::kForInStep: 513 case Bytecode::kThrow: 514 case Bytecode::kReThrow: 515 case Bytecode::kThrowReferenceErrorIfHole: 516 case Bytecode::kThrowSuperNotCalledIfHole: 517 case Bytecode::kThrowSuperAlreadyCalledIfNotHole: 518 case Bytecode::kIllegal: 519 case Bytecode::kCallJSRuntime: 520 case Bytecode::kStackCheck: 521 case Bytecode::kReturn: 522 case Bytecode::kSetPendingMessage: 523 return true; 524 default: 525 return false; 526 } 527 } 528 529 DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) { 530 switch (id) { 531 // Whitelist for builtins. 532 // Object builtins. 533 case Builtins::kObjectConstructor: 534 case Builtins::kObjectCreate: 535 case Builtins::kObjectEntries: 536 case Builtins::kObjectGetOwnPropertyDescriptor: 537 case Builtins::kObjectGetOwnPropertyDescriptors: 538 case Builtins::kObjectGetOwnPropertyNames: 539 case Builtins::kObjectGetOwnPropertySymbols: 540 case Builtins::kObjectGetPrototypeOf: 541 case Builtins::kObjectIs: 542 case Builtins::kObjectIsExtensible: 543 case Builtins::kObjectIsFrozen: 544 case Builtins::kObjectIsSealed: 545 case Builtins::kObjectPrototypeValueOf: 546 case Builtins::kObjectValues: 547 case Builtins::kObjectPrototypeHasOwnProperty: 548 case Builtins::kObjectPrototypeIsPrototypeOf: 549 case Builtins::kObjectPrototypePropertyIsEnumerable: 550 case Builtins::kObjectPrototypeToString: 551 // Array builtins. 552 case Builtins::kArrayIsArray: 553 case Builtins::kArrayConstructor: 554 case Builtins::kArrayIndexOf: 555 case Builtins::kArrayPrototypeValues: 556 case Builtins::kArrayIncludes: 557 case Builtins::kArrayPrototypeEntries: 558 case Builtins::kArrayPrototypeFill: 559 case Builtins::kArrayPrototypeFind: 560 case Builtins::kArrayPrototypeFindIndex: 561 case Builtins::kArrayPrototypeFlat: 562 case Builtins::kArrayPrototypeFlatMap: 563 case Builtins::kArrayPrototypeKeys: 564 case Builtins::kArrayPrototypeSlice: 565 case Builtins::kArrayPrototypeSort: 566 case Builtins::kArrayForEach: 567 case Builtins::kArrayEvery: 568 case Builtins::kArraySome: 569 case Builtins::kArrayConcat: 570 case Builtins::kArrayFilter: 571 case Builtins::kArrayMap: 572 case Builtins::kArrayReduce: 573 case Builtins::kArrayReduceRight: 574 // Trace builtins. 575 case Builtins::kIsTraceCategoryEnabled: 576 case Builtins::kTrace: 577 // TypedArray builtins. 578 case Builtins::kTypedArrayConstructor: 579 case Builtins::kTypedArrayPrototypeBuffer: 580 case Builtins::kTypedArrayPrototypeByteLength: 581 case Builtins::kTypedArrayPrototypeByteOffset: 582 case Builtins::kTypedArrayPrototypeLength: 583 case Builtins::kTypedArrayPrototypeEntries: 584 case Builtins::kTypedArrayPrototypeKeys: 585 case Builtins::kTypedArrayPrototypeValues: 586 case Builtins::kTypedArrayPrototypeFind: 587 case Builtins::kTypedArrayPrototypeFindIndex: 588 case Builtins::kTypedArrayPrototypeIncludes: 589 case Builtins::kTypedArrayPrototypeIndexOf: 590 case Builtins::kTypedArrayPrototypeLastIndexOf: 591 case Builtins::kTypedArrayPrototypeSlice: 592 case Builtins::kTypedArrayPrototypeSubArray: 593 case Builtins::kTypedArrayPrototypeEvery: 594 case Builtins::kTypedArrayPrototypeSome: 595 case Builtins::kTypedArrayPrototypeFilter: 596 case Builtins::kTypedArrayPrototypeMap: 597 case Builtins::kTypedArrayPrototypeReduce: 598 case Builtins::kTypedArrayPrototypeReduceRight: 599 case Builtins::kTypedArrayPrototypeForEach: 600 // ArrayBuffer builtins. 601 case Builtins::kArrayBufferConstructor: 602 case Builtins::kArrayBufferPrototypeGetByteLength: 603 case Builtins::kArrayBufferIsView: 604 case Builtins::kArrayBufferPrototypeSlice: 605 case Builtins::kReturnReceiver: 606 // DataView builtins. 607 case Builtins::kDataViewConstructor: 608 case Builtins::kDataViewPrototypeGetBuffer: 609 case Builtins::kDataViewPrototypeGetByteLength: 610 case Builtins::kDataViewPrototypeGetByteOffset: 611 case Builtins::kDataViewPrototypeGetInt8: 612 case Builtins::kDataViewPrototypeGetUint8: 613 case Builtins::kDataViewPrototypeGetInt16: 614 case Builtins::kDataViewPrototypeGetUint16: 615 case Builtins::kDataViewPrototypeGetInt32: 616 case Builtins::kDataViewPrototypeGetUint32: 617 case Builtins::kDataViewPrototypeGetFloat32: 618 case Builtins::kDataViewPrototypeGetFloat64: 619 case Builtins::kDataViewPrototypeGetBigInt64: 620 case Builtins::kDataViewPrototypeGetBigUint64: 621 // Boolean bulitins. 622 case Builtins::kBooleanConstructor: 623 case Builtins::kBooleanPrototypeToString: 624 case Builtins::kBooleanPrototypeValueOf: 625 // Date builtins. 626 case Builtins::kDateConstructor: 627 case Builtins::kDateNow: 628 case Builtins::kDateParse: 629 case Builtins::kDatePrototypeGetDate: 630 case Builtins::kDatePrototypeGetDay: 631 case Builtins::kDatePrototypeGetFullYear: 632 case Builtins::kDatePrototypeGetHours: 633 case Builtins::kDatePrototypeGetMilliseconds: 634 case Builtins::kDatePrototypeGetMinutes: 635 case Builtins::kDatePrototypeGetMonth: 636 case Builtins::kDatePrototypeGetSeconds: 637 case Builtins::kDatePrototypeGetTime: 638 case Builtins::kDatePrototypeGetTimezoneOffset: 639 case Builtins::kDatePrototypeGetUTCDate: 640 case Builtins::kDatePrototypeGetUTCDay: 641 case Builtins::kDatePrototypeGetUTCFullYear: 642 case Builtins::kDatePrototypeGetUTCHours: 643 case Builtins::kDatePrototypeGetUTCMilliseconds: 644 case Builtins::kDatePrototypeGetUTCMinutes: 645 case Builtins::kDatePrototypeGetUTCMonth: 646 case Builtins::kDatePrototypeGetUTCSeconds: 647 case Builtins::kDatePrototypeGetYear: 648 case Builtins::kDatePrototypeToDateString: 649 case Builtins::kDatePrototypeToISOString: 650 case Builtins::kDatePrototypeToUTCString: 651 case Builtins::kDatePrototypeToString: 652 case Builtins::kDatePrototypeToTimeString: 653 case Builtins::kDatePrototypeToJson: 654 case Builtins::kDatePrototypeToPrimitive: 655 case Builtins::kDatePrototypeValueOf: 656 // Map builtins. 657 case Builtins::kMapConstructor: 658 case Builtins::kMapPrototypeForEach: 659 case Builtins::kMapPrototypeGet: 660 case Builtins::kMapPrototypeHas: 661 case Builtins::kMapPrototypeEntries: 662 case Builtins::kMapPrototypeGetSize: 663 case Builtins::kMapPrototypeKeys: 664 case Builtins::kMapPrototypeValues: 665 // WeakMap builtins. 666 case Builtins::kWeakMapConstructor: 667 case Builtins::kWeakMapGet: 668 case Builtins::kWeakMapHas: 669 // Math builtins. 670 case Builtins::kMathAbs: 671 case Builtins::kMathAcos: 672 case Builtins::kMathAcosh: 673 case Builtins::kMathAsin: 674 case Builtins::kMathAsinh: 675 case Builtins::kMathAtan: 676 case Builtins::kMathAtanh: 677 case Builtins::kMathAtan2: 678 case Builtins::kMathCeil: 679 case Builtins::kMathCbrt: 680 case Builtins::kMathExpm1: 681 case Builtins::kMathClz32: 682 case Builtins::kMathCos: 683 case Builtins::kMathCosh: 684 case Builtins::kMathExp: 685 case Builtins::kMathFloor: 686 case Builtins::kMathFround: 687 case Builtins::kMathHypot: 688 case Builtins::kMathImul: 689 case Builtins::kMathLog: 690 case Builtins::kMathLog1p: 691 case Builtins::kMathLog2: 692 case Builtins::kMathLog10: 693 case Builtins::kMathMax: 694 case Builtins::kMathMin: 695 case Builtins::kMathPow: 696 case Builtins::kMathRandom: 697 case Builtins::kMathRound: 698 case Builtins::kMathSign: 699 case Builtins::kMathSin: 700 case Builtins::kMathSinh: 701 case Builtins::kMathSqrt: 702 case Builtins::kMathTan: 703 case Builtins::kMathTanh: 704 case Builtins::kMathTrunc: 705 // Number builtins. 706 case Builtins::kNumberConstructor: 707 case Builtins::kNumberIsFinite: 708 case Builtins::kNumberIsInteger: 709 case Builtins::kNumberIsNaN: 710 case Builtins::kNumberIsSafeInteger: 711 case Builtins::kNumberParseFloat: 712 case Builtins::kNumberParseInt: 713 case Builtins::kNumberPrototypeToExponential: 714 case Builtins::kNumberPrototypeToFixed: 715 case Builtins::kNumberPrototypeToPrecision: 716 case Builtins::kNumberPrototypeToString: 717 case Builtins::kNumberPrototypeValueOf: 718 // BigInt builtins. 719 case Builtins::kBigIntConstructor: 720 case Builtins::kBigIntAsIntN: 721 case Builtins::kBigIntAsUintN: 722 case Builtins::kBigIntPrototypeToString: 723 case Builtins::kBigIntPrototypeValueOf: 724 // Set builtins. 725 case Builtins::kSetConstructor: 726 case Builtins::kSetPrototypeEntries: 727 case Builtins::kSetPrototypeForEach: 728 case Builtins::kSetPrototypeGetSize: 729 case Builtins::kSetPrototypeHas: 730 case Builtins::kSetPrototypeValues: 731 // WeakSet builtins. 732 case Builtins::kWeakSetConstructor: 733 case Builtins::kWeakSetHas: 734 // String builtins. Strings are immutable. 735 case Builtins::kStringFromCharCode: 736 case Builtins::kStringFromCodePoint: 737 case Builtins::kStringConstructor: 738 case Builtins::kStringPrototypeAnchor: 739 case Builtins::kStringPrototypeBig: 740 case Builtins::kStringPrototypeBlink: 741 case Builtins::kStringPrototypeBold: 742 case Builtins::kStringPrototypeCharAt: 743 case Builtins::kStringPrototypeCharCodeAt: 744 case Builtins::kStringPrototypeCodePointAt: 745 case Builtins::kStringPrototypeConcat: 746 case Builtins::kStringPrototypeEndsWith: 747 case Builtins::kStringPrototypeFixed: 748 case Builtins::kStringPrototypeFontcolor: 749 case Builtins::kStringPrototypeFontsize: 750 case Builtins::kStringPrototypeIncludes: 751 case Builtins::kStringPrototypeIndexOf: 752 case Builtins::kStringPrototypeItalics: 753 case Builtins::kStringPrototypeLastIndexOf: 754 case Builtins::kStringPrototypeLink: 755 case Builtins::kStringPrototypePadEnd: 756 case Builtins::kStringPrototypePadStart: 757 case Builtins::kStringPrototypeRepeat: 758 case Builtins::kStringPrototypeSlice: 759 case Builtins::kStringPrototypeSmall: 760 case Builtins::kStringPrototypeStartsWith: 761 case Builtins::kStringPrototypeStrike: 762 case Builtins::kStringPrototypeSub: 763 case Builtins::kStringPrototypeSubstr: 764 case Builtins::kStringPrototypeSubstring: 765 case Builtins::kStringPrototypeSup: 766 case Builtins::kStringPrototypeToString: 767 #ifndef V8_INTL_SUPPORT 768 case Builtins::kStringPrototypeToLowerCase: 769 case Builtins::kStringPrototypeToUpperCase: 770 #endif 771 case Builtins::kStringPrototypeTrim: 772 case Builtins::kStringPrototypeTrimEnd: 773 case Builtins::kStringPrototypeTrimStart: 774 case Builtins::kStringPrototypeValueOf: 775 case Builtins::kStringToNumber: 776 case Builtins::kStringSubstring: 777 // Symbol builtins. 778 case Builtins::kSymbolConstructor: 779 case Builtins::kSymbolKeyFor: 780 case Builtins::kSymbolPrototypeToString: 781 case Builtins::kSymbolPrototypeValueOf: 782 case Builtins::kSymbolPrototypeToPrimitive: 783 // JSON builtins. 784 case Builtins::kJsonParse: 785 case Builtins::kJsonStringify: 786 // Global function builtins. 787 case Builtins::kGlobalDecodeURI: 788 case Builtins::kGlobalDecodeURIComponent: 789 case Builtins::kGlobalEncodeURI: 790 case Builtins::kGlobalEncodeURIComponent: 791 case Builtins::kGlobalEscape: 792 case Builtins::kGlobalUnescape: 793 case Builtins::kGlobalIsFinite: 794 case Builtins::kGlobalIsNaN: 795 // Function builtins. 796 case Builtins::kFunctionPrototypeToString: 797 case Builtins::kFunctionPrototypeBind: 798 case Builtins::kFastFunctionPrototypeBind: 799 case Builtins::kFunctionPrototypeCall: 800 case Builtins::kFunctionPrototypeApply: 801 // Error builtins. 802 case Builtins::kErrorConstructor: 803 case Builtins::kMakeError: 804 case Builtins::kMakeTypeError: 805 case Builtins::kMakeSyntaxError: 806 case Builtins::kMakeRangeError: 807 case Builtins::kMakeURIError: 808 // RegExp builtins. 809 case Builtins::kRegExpConstructor: 810 return DebugInfo::kHasNoSideEffect; 811 // Set builtins. 812 case Builtins::kSetIteratorPrototypeNext: 813 case Builtins::kSetPrototypeAdd: 814 case Builtins::kSetPrototypeClear: 815 case Builtins::kSetPrototypeDelete: 816 // Array builtins. 817 case Builtins::kArrayIteratorPrototypeNext: 818 case Builtins::kArrayPrototypePop: 819 case Builtins::kArrayPrototypePush: 820 case Builtins::kArrayPrototypeReverse: 821 case Builtins::kArrayPrototypeShift: 822 case Builtins::kArraySplice: 823 case Builtins::kArrayUnshift: 824 // Map builtins. 825 case Builtins::kMapIteratorPrototypeNext: 826 case Builtins::kMapPrototypeClear: 827 case Builtins::kMapPrototypeDelete: 828 case Builtins::kMapPrototypeSet: 829 // RegExp builtins. 830 case Builtins::kRegExpPrototypeTest: 831 case Builtins::kRegExpPrototypeExec: 832 case Builtins::kRegExpPrototypeSplit: 833 case Builtins::kRegExpPrototypeFlagsGetter: 834 case Builtins::kRegExpPrototypeGlobalGetter: 835 case Builtins::kRegExpPrototypeIgnoreCaseGetter: 836 case Builtins::kRegExpPrototypeMultilineGetter: 837 case Builtins::kRegExpPrototypeDotAllGetter: 838 case Builtins::kRegExpPrototypeUnicodeGetter: 839 case Builtins::kRegExpPrototypeStickyGetter: 840 return DebugInfo::kRequiresRuntimeChecks; 841 default: 842 if (FLAG_trace_side_effect_free_debug_evaluate) { 843 PrintF("[debug-evaluate] built-in %s may cause side effect.\n", 844 Builtins::name(id)); 845 } 846 return DebugInfo::kHasSideEffects; 847 } 848 } 849 850 bool BytecodeRequiresRuntimeCheck(interpreter::Bytecode bytecode) { 851 typedef interpreter::Bytecode Bytecode; 852 switch (bytecode) { 853 case Bytecode::kStaNamedProperty: 854 case Bytecode::kStaNamedOwnProperty: 855 case Bytecode::kStaKeyedProperty: 856 case Bytecode::kStaInArrayLiteral: 857 case Bytecode::kStaDataPropertyInLiteral: 858 case Bytecode::kStaCurrentContextSlot: 859 return true; 860 default: 861 return false; 862 } 863 } 864 865 } // anonymous namespace 866 867 // static 868 DebugInfo::SideEffectState DebugEvaluate::FunctionGetSideEffectState( 869 Isolate* isolate, Handle<SharedFunctionInfo> info) { 870 if (FLAG_trace_side_effect_free_debug_evaluate) { 871 PrintF("[debug-evaluate] Checking function %s for side effect.\n", 872 info->DebugName()->ToCString().get()); 873 } 874 875 DCHECK(info->is_compiled()); 876 if (info->HasBytecodeArray()) { 877 // Check bytecodes against whitelist. 878 Handle<BytecodeArray> bytecode_array(info->GetBytecodeArray(), isolate); 879 if (FLAG_trace_side_effect_free_debug_evaluate) { 880 bytecode_array->Print(); 881 } 882 bool requires_runtime_checks = false; 883 for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done(); 884 it.Advance()) { 885 interpreter::Bytecode bytecode = it.current_bytecode(); 886 887 if (interpreter::Bytecodes::IsCallRuntime(bytecode)) { 888 Runtime::FunctionId id = 889 (bytecode == interpreter::Bytecode::kInvokeIntrinsic) 890 ? it.GetIntrinsicIdOperand(0) 891 : it.GetRuntimeIdOperand(0); 892 if (IntrinsicHasNoSideEffect(id)) continue; 893 return DebugInfo::kHasSideEffects; 894 } 895 896 if (BytecodeHasNoSideEffect(bytecode)) continue; 897 if (BytecodeRequiresRuntimeCheck(bytecode)) { 898 requires_runtime_checks = true; 899 continue; 900 } 901 902 if (FLAG_trace_side_effect_free_debug_evaluate) { 903 PrintF("[debug-evaluate] bytecode %s may cause side effect.\n", 904 interpreter::Bytecodes::ToString(bytecode)); 905 } 906 907 // Did not match whitelist. 908 return DebugInfo::kHasSideEffects; 909 } 910 return requires_runtime_checks ? DebugInfo::kRequiresRuntimeChecks 911 : DebugInfo::kHasNoSideEffect; 912 } else if (info->IsApiFunction()) { 913 if (info->GetCode()->is_builtin()) { 914 return info->GetCode()->builtin_index() == Builtins::kHandleApiCall 915 ? DebugInfo::kHasNoSideEffect 916 : DebugInfo::kHasSideEffects; 917 } 918 } else { 919 // Check built-ins against whitelist. 920 int builtin_index = 921 info->HasBuiltinId() ? info->builtin_id() : Builtins::kNoBuiltinId; 922 DCHECK_NE(Builtins::kDeserializeLazy, builtin_index); 923 if (!Builtins::IsBuiltinId(builtin_index)) 924 return DebugInfo::kHasSideEffects; 925 DebugInfo::SideEffectState state = 926 BuiltinGetSideEffectState(static_cast<Builtins::Name>(builtin_index)); 927 #ifdef DEBUG 928 if (state == DebugInfo::kHasNoSideEffect) { 929 Code* code = isolate->builtins()->builtin(builtin_index); 930 if (code->builtin_index() == Builtins::kDeserializeLazy) { 931 // Target builtin is not yet deserialized. Deserialize it now. 932 933 DCHECK(Builtins::IsLazy(builtin_index)); 934 DCHECK_EQ(Builtins::TFJ, Builtins::KindOf(builtin_index)); 935 936 code = Snapshot::DeserializeBuiltin(isolate, builtin_index); 937 DCHECK_NE(Builtins::kDeserializeLazy, code->builtin_index()); 938 } 939 // TODO(yangguo): Check builtin-to-builtin calls too. 940 int mode = RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE); 941 bool failed = false; 942 for (RelocIterator it(code, mode); !it.done(); it.next()) { 943 RelocInfo* rinfo = it.rinfo(); 944 Address address = rinfo->target_external_reference(); 945 const Runtime::Function* function = Runtime::FunctionForEntry(address); 946 if (function == nullptr) continue; 947 if (!BuiltinToIntrinsicHasNoSideEffect( 948 static_cast<Builtins::Name>(builtin_index), 949 function->function_id)) { 950 PrintF("Whitelisted builtin %s calls non-whitelisted intrinsic %s\n", 951 Builtins::name(builtin_index), function->name); 952 failed = true; 953 } 954 DCHECK(!failed); 955 } 956 } 957 #endif // DEBUG 958 return state; 959 } 960 961 return DebugInfo::kHasSideEffects; 962 } 963 964 // static 965 bool DebugEvaluate::CallbackHasNoSideEffect(Object* callback_info) { 966 DisallowHeapAllocation no_gc; 967 if (callback_info->IsAccessorInfo()) { 968 // List of whitelisted internal accessors can be found in accessors.h. 969 AccessorInfo* info = AccessorInfo::cast(callback_info); 970 if (info->has_no_side_effect()) return true; 971 if (FLAG_trace_side_effect_free_debug_evaluate) { 972 PrintF("[debug-evaluate] API Callback '"); 973 info->name()->ShortPrint(); 974 PrintF("' may cause side effect.\n"); 975 } 976 } else if (callback_info->IsInterceptorInfo()) { 977 InterceptorInfo* info = InterceptorInfo::cast(callback_info); 978 if (info->has_no_side_effect()) return true; 979 if (FLAG_trace_side_effect_free_debug_evaluate) { 980 PrintF("[debug-evaluate] API Interceptor may cause side effect.\n"); 981 } 982 } else if (callback_info->IsCallHandlerInfo()) { 983 CallHandlerInfo* info = CallHandlerInfo::cast(callback_info); 984 if (info->IsSideEffectFreeCallHandlerInfo()) return true; 985 if (FLAG_trace_side_effect_free_debug_evaluate) { 986 PrintF("[debug-evaluate] API CallHandlerInfo may cause side effect.\n"); 987 } 988 } 989 return false; 990 } 991 992 // static 993 void DebugEvaluate::ApplySideEffectChecks( 994 Handle<BytecodeArray> bytecode_array) { 995 for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done(); 996 it.Advance()) { 997 interpreter::Bytecode bytecode = it.current_bytecode(); 998 if (BytecodeRequiresRuntimeCheck(bytecode)) it.ApplyDebugBreak(); 999 } 1000 } 1001 1002 } // namespace internal 1003 } // namespace v8 1004