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