Line data Source code
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 9248 : 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 9248 : 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 9248 : ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE);
38 :
39 : Handle<SharedFunctionInfo> shared_info;
40 9248 : if (!maybe_function_info.ToHandle(&shared_info)) return MaybeHandle<Object>();
41 :
42 : Handle<JSFunction> fun =
43 : isolate->factory()->NewFunctionFromSharedFunctionInfo(shared_info,
44 9213 : context);
45 9213 : if (throw_on_side_effect) isolate->debug()->StartSideEffectCheckMode();
46 : MaybeHandle<Object> result = Execution::Call(
47 18426 : isolate, fun, Handle<JSObject>(context->global_proxy(), isolate), 0,
48 9213 : nullptr);
49 9213 : if (throw_on_side_effect) isolate->debug()->StopSideEffectCheckMode();
50 9213 : return result;
51 : }
52 :
53 12167 : 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 12167 : StackTraceFrameIterator it(isolate, frame_id);
63 12167 : 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 24334 : ContextBuilder context_builder(isolate, frame, inlined_jsframe_index);
73 12167 : if (isolate->has_pending_exception()) return MaybeHandle<Object>();
74 :
75 : Handle<Context> context = context_builder.evaluation_context();
76 24334 : Handle<JSObject> receiver(context->global_proxy(), isolate);
77 : MaybeHandle<Object> maybe_result =
78 : Evaluate(isolate, context_builder.outer_info(), context, receiver, source,
79 24334 : throw_on_side_effect);
80 12167 : if (!maybe_result.is_null()) context_builder.UpdateValues();
81 12167 : return maybe_result;
82 : }
83 :
84 85 : 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 85 : JavaScriptFrameIterator it(isolate);
90 :
91 : // Get context and receiver.
92 : Handle<Context> native_context(
93 85 : Context::cast(it.frame()->context())->native_context(), isolate);
94 :
95 : // Materialize arguments as property on an extension object.
96 85 : Handle<JSObject> materialized = factory->NewJSObjectWithNullProto();
97 : Handle<String> arguments_str = factory->arguments_string();
98 170 : JSObject::SetOwnPropertyIgnoreAttributes(
99 : materialized, arguments_str,
100 170 : Accessors::FunctionGetArguments(it.frame(), 0), NONE)
101 : .Check();
102 :
103 : // Materialize receiver.
104 : Handle<String> this_str = factory->this_string();
105 170 : JSObject::SetOwnPropertyIgnoreAttributes(
106 85 : materialized, this_str, Handle<Object>(it.frame()->receiver(), isolate),
107 170 : NONE)
108 : .Check();
109 :
110 : // Use extension object in a debug-evaluate scope.
111 : Handle<ScopeInfo> scope_info =
112 85 : ScopeInfo::CreateForWithScope(isolate, Handle<ScopeInfo>::null());
113 85 : scope_info->SetIsDebugEvaluateScope();
114 : Handle<Context> evaluation_context =
115 : factory->NewDebugEvaluateContext(native_context, scope_info, materialized,
116 85 : Handle<Context>(), Handle<StringSet>());
117 : Handle<SharedFunctionInfo> outer_info(
118 170 : native_context->empty_function()->shared(), isolate);
119 170 : 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 85 : throw_on_side_effect);
124 170 : return maybe_result;
125 : }
126 :
127 : // Compile and evaluate source for the given context.
128 12252 : 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 24504 : 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 12161 : if (throw_on_side_effect) isolate->debug()->StartSideEffectCheckMode();
144 24322 : success = Execution::Call(isolate, eval_fun, receiver, 0, nullptr)
145 : .ToHandle(&result);
146 12161 : if (throw_on_side_effect) isolate->debug()->StopSideEffectCheckMode();
147 : if (!success) DCHECK(isolate->has_pending_exception());
148 13252 : return success ? result : MaybeHandle<Object>();
149 : }
150 :
151 12167 : Handle<SharedFunctionInfo> DebugEvaluate::ContextBuilder::outer_info() const {
152 24334 : return handle(frame_inspector_.GetFunction()->shared(), isolate_);
153 : }
154 :
155 12167 : 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 12167 : ScopeIterator::COLLECT_NON_LOCALS) {
162 : Handle<Context> outer_context(frame_inspector_.GetFunction()->context(),
163 : isolate);
164 12167 : evaluation_context_ = outer_context;
165 : Factory* factory = isolate->factory();
166 :
167 12167 : 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 37023 : for (; scope_iterator_.InInnerScope(); scope_iterator_.Next()) {
186 12650 : ScopeIterator::ScopeType scope_type = scope_iterator_.Type();
187 12650 : if (scope_type == ScopeIterator::ScopeTypeScript) break;
188 : ContextChainElement context_chain_element;
189 13241 : if (scope_type == ScopeIterator::ScopeTypeLocal ||
190 799 : scope_iterator_.DeclaresLocals(ScopeIterator::Mode::STACK)) {
191 : context_chain_element.materialized_object =
192 12110 : scope_iterator_.ScopeObject(ScopeIterator::Mode::STACK);
193 : }
194 12442 : if (scope_iterator_.HasContext()) {
195 1064 : context_chain_element.wrapped_context = scope_iterator_.CurrentContext();
196 : }
197 12442 : if (scope_type == ScopeIterator::ScopeTypeLocal) {
198 11643 : context_chain_element.whitelist = scope_iterator_.GetNonLocals();
199 : }
200 12442 : context_chain_.push_back(context_chain_element);
201 : }
202 :
203 : Handle<ScopeInfo> scope_info =
204 : evaluation_context_->IsNativeContext()
205 : ? Handle<ScopeInfo>::null()
206 26172 : : handle(evaluation_context_->scope_info(), isolate);
207 24581 : for (auto rit = context_chain_.rbegin(); rit != context_chain_.rend();
208 : rit++) {
209 12442 : ContextChainElement element = *rit;
210 12442 : scope_info = ScopeInfo::CreateForWithScope(isolate, scope_info);
211 12442 : scope_info->SetIsDebugEvaluateScope();
212 : evaluation_context_ = factory->NewDebugEvaluateContext(
213 : evaluation_context_, scope_info, element.materialized_object,
214 12442 : element.wrapped_context, element.whitelist);
215 : }
216 : }
217 :
218 10985 : void DebugEvaluate::ContextBuilder::UpdateValues() {
219 10985 : scope_iterator_.Restart();
220 22295 : for (ContextChainElement& element : context_chain_) {
221 11310 : if (!element.materialized_object.is_null()) {
222 : Handle<FixedArray> keys =
223 21956 : KeyAccumulator::GetKeys(element.materialized_object,
224 : KeyCollectionMode::kOwnOnly,
225 10978 : ENUMERABLE_STRINGS)
226 : .ToHandleChecked();
227 :
228 178842 : for (int i = 0; i < keys->length(); i++) {
229 : DCHECK(keys->get(i)->IsString());
230 83932 : Handle<String> key(String::cast(keys->get(i)), isolate_);
231 : Handle<Object> value =
232 83932 : JSReceiver::GetDataProperty(element.materialized_object, key);
233 83932 : scope_iterator_.SetVariableValue(key, value);
234 : }
235 : }
236 11310 : scope_iterator_.Next();
237 : }
238 10985 : }
239 :
240 : namespace {
241 :
242 1328 : bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
243 : // Use macro to include only the non-inlined version of an intrinsic.
244 : #define INTRINSIC_WHITELIST(V) \
245 : /* Conversions */ \
246 : V(NumberToString) \
247 : V(ToBigInt) \
248 : V(ToLength) \
249 : V(ToNumber) \
250 : V(ToObject) \
251 : V(ToString) \
252 : /* Type checks */ \
253 : V(IsArray) \
254 : V(IsFunction) \
255 : V(IsJSProxy) \
256 : V(IsJSReceiver) \
257 : V(IsRegExp) \
258 : V(IsSmi) \
259 : V(IsTypedArray) \
260 : /* Loads */ \
261 : V(LoadLookupSlotForCall) \
262 : V(GetProperty) \
263 : /* Arrays */ \
264 : V(ArraySpeciesConstructor) \
265 : V(EstimateNumberOfElements) \
266 : V(GetArrayKeys) \
267 : V(HasComplexElements) \
268 : V(HasFastPackedElements) \
269 : V(NewArray) \
270 : V(NormalizeElements) \
271 : V(PrepareElementsForSort) \
272 : V(TrySliceSimpleNonFastElements) \
273 : V(TypedArrayGetBuffer) \
274 : /* Errors */ \
275 : V(NewTypeError) \
276 : V(ReThrow) \
277 : V(ThrowCalledNonCallable) \
278 : V(ThrowInvalidStringLength) \
279 : V(ThrowIteratorError) \
280 : V(ThrowIteratorResultNotAnObject) \
281 : V(ThrowPatternAssignmentNonCoercible) \
282 : V(ThrowReferenceError) \
283 : V(ThrowSymbolIteratorInvalid) \
284 : /* Strings */ \
285 : V(StringIncludes) \
286 : V(StringIndexOf) \
287 : V(StringReplaceOneCharWithString) \
288 : V(StringSubstring) \
289 : V(StringToNumber) \
290 : V(StringTrim) \
291 : /* BigInts */ \
292 : V(BigIntEqualToBigInt) \
293 : V(BigIntToBoolean) \
294 : V(BigIntToNumber) \
295 : /* Literals */ \
296 : V(CreateArrayLiteral) \
297 : V(CreateArrayLiteralWithoutAllocationSite) \
298 : V(CreateObjectLiteral) \
299 : V(CreateObjectLiteralWithoutAllocationSite) \
300 : V(CreateRegExpLiteral) \
301 : /* Called from builtins */ \
302 : V(AllocateInYoungGeneration) \
303 : V(AllocateInOldGeneration) \
304 : V(AllocateSeqOneByteString) \
305 : V(AllocateSeqTwoByteString) \
306 : V(ArrayIncludes_Slow) \
307 : V(ArrayIndexOf) \
308 : V(ArrayIsArray) \
309 : V(ClassOf) \
310 : V(GetFunctionName) \
311 : V(GetOwnPropertyDescriptor) \
312 : V(GlobalPrint) \
313 : V(HasProperty) \
314 : V(ObjectCreate) \
315 : V(ObjectEntries) \
316 : V(ObjectEntriesSkipFastPath) \
317 : V(ObjectHasOwnProperty) \
318 : V(ObjectValues) \
319 : V(ObjectValuesSkipFastPath) \
320 : V(ObjectGetOwnPropertyNames) \
321 : V(ObjectGetOwnPropertyNamesTryFast) \
322 : V(RegExpInitializeAndCompile) \
323 : V(StackGuard) \
324 : V(StringAdd) \
325 : V(StringCharCodeAt) \
326 : V(StringEqual) \
327 : V(StringIndexOfUnchecked) \
328 : V(StringParseFloat) \
329 : V(StringParseInt) \
330 : V(SymbolDescriptiveString) \
331 : V(ThrowRangeError) \
332 : V(ThrowTypeError) \
333 : V(ToName) \
334 : V(TransitionElementsKind) \
335 : /* Misc. */ \
336 : V(Call) \
337 : V(CompleteInobjectSlackTrackingForMap) \
338 : V(HasInPrototypeChain) \
339 : V(IncrementUseCounter) \
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 1328 : switch (id) {
359 : INTRINSIC_WHITELIST(CASE)
360 : INLINE_INTRINSIC_WHITELIST(INLINE_CASE)
361 : return true;
362 : default:
363 63 : if (FLAG_trace_side_effect_free_debug_evaluate) {
364 : PrintF("[debug-evaluate] intrinsic %s may cause side effect.\n",
365 0 : 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 72340 : bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
377 : using interpreter::Bytecode;
378 : using interpreter::Bytecodes;
379 72340 : if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) return true;
380 34877 : if (Bytecodes::IsCallOrConstruct(bytecode)) return true;
381 29974 : if (Bytecodes::IsJumpIfToBoolean(bytecode)) return true;
382 29555 : if (Bytecodes::IsPrefixScalingBytecode(bytecode)) return true;
383 29555 : switch (bytecode) {
384 : // Whitelist for bytecodes.
385 : // Loads.
386 : case Bytecode::kLdaLookupSlot:
387 : case Bytecode::kLdaGlobal:
388 : case Bytecode::kLdaNamedProperty:
389 : case Bytecode::kLdaNamedPropertyNoFeedback:
390 : case Bytecode::kLdaKeyedProperty:
391 : case Bytecode::kLdaGlobalInsideTypeof:
392 : case Bytecode::kLdaLookupSlotInsideTypeof:
393 : // Arithmetics.
394 : case Bytecode::kAdd:
395 : case Bytecode::kAddSmi:
396 : case Bytecode::kSub:
397 : case Bytecode::kSubSmi:
398 : case Bytecode::kMul:
399 : case Bytecode::kMulSmi:
400 : case Bytecode::kDiv:
401 : case Bytecode::kDivSmi:
402 : case Bytecode::kMod:
403 : case Bytecode::kModSmi:
404 : case Bytecode::kExp:
405 : case Bytecode::kExpSmi:
406 : case Bytecode::kNegate:
407 : case Bytecode::kBitwiseAnd:
408 : case Bytecode::kBitwiseAndSmi:
409 : case Bytecode::kBitwiseNot:
410 : case Bytecode::kBitwiseOr:
411 : case Bytecode::kBitwiseOrSmi:
412 : case Bytecode::kBitwiseXor:
413 : case Bytecode::kBitwiseXorSmi:
414 : case Bytecode::kShiftLeft:
415 : case Bytecode::kShiftLeftSmi:
416 : case Bytecode::kShiftRight:
417 : case Bytecode::kShiftRightSmi:
418 : case Bytecode::kShiftRightLogical:
419 : case Bytecode::kShiftRightLogicalSmi:
420 : case Bytecode::kInc:
421 : case Bytecode::kDec:
422 : case Bytecode::kLogicalNot:
423 : case Bytecode::kToBooleanLogicalNot:
424 : case Bytecode::kTypeOf:
425 : // Contexts.
426 : case Bytecode::kCreateBlockContext:
427 : case Bytecode::kCreateCatchContext:
428 : case Bytecode::kCreateFunctionContext:
429 : case Bytecode::kCreateEvalContext:
430 : case Bytecode::kCreateWithContext:
431 : // Literals.
432 : case Bytecode::kCreateArrayLiteral:
433 : case Bytecode::kCreateEmptyArrayLiteral:
434 : case Bytecode::kCreateArrayFromIterable:
435 : case Bytecode::kCreateObjectLiteral:
436 : case Bytecode::kCreateEmptyObjectLiteral:
437 : case Bytecode::kCreateRegExpLiteral:
438 : // Allocations.
439 : case Bytecode::kCreateClosure:
440 : case Bytecode::kCreateUnmappedArguments:
441 : case Bytecode::kCreateRestParameter:
442 : // Comparisons.
443 : case Bytecode::kTestEqual:
444 : case Bytecode::kTestEqualStrict:
445 : case Bytecode::kTestLessThan:
446 : case Bytecode::kTestLessThanOrEqual:
447 : case Bytecode::kTestGreaterThan:
448 : case Bytecode::kTestGreaterThanOrEqual:
449 : case Bytecode::kTestInstanceOf:
450 : case Bytecode::kTestIn:
451 : case Bytecode::kTestReferenceEqual:
452 : case Bytecode::kTestUndetectable:
453 : case Bytecode::kTestTypeOf:
454 : case Bytecode::kTestUndefined:
455 : case Bytecode::kTestNull:
456 : // Conversions.
457 : case Bytecode::kToObject:
458 : case Bytecode::kToName:
459 : case Bytecode::kToNumber:
460 : case Bytecode::kToNumeric:
461 : case Bytecode::kToString:
462 : // Misc.
463 : case Bytecode::kForInEnumerate:
464 : case Bytecode::kForInPrepare:
465 : case Bytecode::kForInContinue:
466 : case Bytecode::kForInNext:
467 : case Bytecode::kForInStep:
468 : case Bytecode::kThrow:
469 : case Bytecode::kReThrow:
470 : case Bytecode::kThrowReferenceErrorIfHole:
471 : case Bytecode::kThrowSuperNotCalledIfHole:
472 : case Bytecode::kThrowSuperAlreadyCalledIfNotHole:
473 : case Bytecode::kIllegal:
474 : case Bytecode::kCallJSRuntime:
475 : case Bytecode::kStackCheck:
476 : case Bytecode::kReturn:
477 : case Bytecode::kSetPendingMessage:
478 : return true;
479 : default:
480 2446 : return false;
481 : }
482 : }
483 :
484 6351 : DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) {
485 6351 : switch (id) {
486 : // Whitelist for builtins.
487 : // Object builtins.
488 : case Builtins::kObjectConstructor:
489 : case Builtins::kObjectCreate:
490 : case Builtins::kObjectEntries:
491 : case Builtins::kObjectGetOwnPropertyDescriptor:
492 : case Builtins::kObjectGetOwnPropertyDescriptors:
493 : case Builtins::kObjectGetOwnPropertyNames:
494 : case Builtins::kObjectGetOwnPropertySymbols:
495 : case Builtins::kObjectGetPrototypeOf:
496 : case Builtins::kObjectIs:
497 : case Builtins::kObjectIsExtensible:
498 : case Builtins::kObjectIsFrozen:
499 : case Builtins::kObjectIsSealed:
500 : case Builtins::kObjectPrototypeValueOf:
501 : case Builtins::kObjectValues:
502 : case Builtins::kObjectPrototypeHasOwnProperty:
503 : case Builtins::kObjectPrototypeIsPrototypeOf:
504 : case Builtins::kObjectPrototypePropertyIsEnumerable:
505 : case Builtins::kObjectPrototypeToString:
506 : case Builtins::kObjectPrototypeToLocaleString:
507 : // Array builtins.
508 : case Builtins::kArrayIsArray:
509 : case Builtins::kArrayConstructor:
510 : case Builtins::kArrayIndexOf:
511 : case Builtins::kArrayPrototypeValues:
512 : case Builtins::kArrayIncludes:
513 : case Builtins::kArrayPrototypeEntries:
514 : case Builtins::kArrayPrototypeFill:
515 : case Builtins::kArrayPrototypeFind:
516 : case Builtins::kArrayPrototypeFindIndex:
517 : case Builtins::kArrayPrototypeFlat:
518 : case Builtins::kArrayPrototypeFlatMap:
519 : case Builtins::kArrayPrototypeJoin:
520 : case Builtins::kArrayPrototypeKeys:
521 : case Builtins::kArrayPrototypeLastIndexOf:
522 : case Builtins::kArrayPrototypeSlice:
523 : case Builtins::kArrayPrototypeSort:
524 : case Builtins::kArrayPrototypeToLocaleString:
525 : case Builtins::kArrayPrototypeToString:
526 : case Builtins::kArrayForEach:
527 : case Builtins::kArrayEvery:
528 : case Builtins::kArraySome:
529 : case Builtins::kArrayConcat:
530 : case Builtins::kArrayFilter:
531 : case Builtins::kArrayMap:
532 : case Builtins::kArrayReduce:
533 : case Builtins::kArrayReduceRight:
534 : // Trace builtins.
535 : case Builtins::kIsTraceCategoryEnabled:
536 : case Builtins::kTrace:
537 : // TypedArray builtins.
538 : case Builtins::kTypedArrayConstructor:
539 : case Builtins::kTypedArrayPrototypeBuffer:
540 : case Builtins::kTypedArrayPrototypeByteLength:
541 : case Builtins::kTypedArrayPrototypeByteOffset:
542 : case Builtins::kTypedArrayPrototypeLength:
543 : case Builtins::kTypedArrayPrototypeEntries:
544 : case Builtins::kTypedArrayPrototypeKeys:
545 : case Builtins::kTypedArrayPrototypeValues:
546 : case Builtins::kTypedArrayPrototypeFind:
547 : case Builtins::kTypedArrayPrototypeFindIndex:
548 : case Builtins::kTypedArrayPrototypeIncludes:
549 : case Builtins::kTypedArrayPrototypeJoin:
550 : case Builtins::kTypedArrayPrototypeIndexOf:
551 : case Builtins::kTypedArrayPrototypeLastIndexOf:
552 : case Builtins::kTypedArrayPrototypeSlice:
553 : case Builtins::kTypedArrayPrototypeSubArray:
554 : case Builtins::kTypedArrayPrototypeEvery:
555 : case Builtins::kTypedArrayPrototypeSome:
556 : case Builtins::kTypedArrayPrototypeToLocaleString:
557 : case Builtins::kTypedArrayPrototypeFilter:
558 : case Builtins::kTypedArrayPrototypeMap:
559 : case Builtins::kTypedArrayPrototypeReduce:
560 : case Builtins::kTypedArrayPrototypeReduceRight:
561 : case Builtins::kTypedArrayPrototypeForEach:
562 : // ArrayBuffer builtins.
563 : case Builtins::kArrayBufferConstructor:
564 : case Builtins::kArrayBufferPrototypeGetByteLength:
565 : case Builtins::kArrayBufferIsView:
566 : case Builtins::kArrayBufferPrototypeSlice:
567 : case Builtins::kReturnReceiver:
568 : // DataView builtins.
569 : case Builtins::kDataViewConstructor:
570 : case Builtins::kDataViewPrototypeGetBuffer:
571 : case Builtins::kDataViewPrototypeGetByteLength:
572 : case Builtins::kDataViewPrototypeGetByteOffset:
573 : case Builtins::kDataViewPrototypeGetInt8:
574 : case Builtins::kDataViewPrototypeGetUint8:
575 : case Builtins::kDataViewPrototypeGetInt16:
576 : case Builtins::kDataViewPrototypeGetUint16:
577 : case Builtins::kDataViewPrototypeGetInt32:
578 : case Builtins::kDataViewPrototypeGetUint32:
579 : case Builtins::kDataViewPrototypeGetFloat32:
580 : case Builtins::kDataViewPrototypeGetFloat64:
581 : case Builtins::kDataViewPrototypeGetBigInt64:
582 : case Builtins::kDataViewPrototypeGetBigUint64:
583 : // Boolean bulitins.
584 : case Builtins::kBooleanConstructor:
585 : case Builtins::kBooleanPrototypeToString:
586 : case Builtins::kBooleanPrototypeValueOf:
587 : // Date builtins.
588 : case Builtins::kDateConstructor:
589 : case Builtins::kDateNow:
590 : case Builtins::kDateParse:
591 : case Builtins::kDatePrototypeGetDate:
592 : case Builtins::kDatePrototypeGetDay:
593 : case Builtins::kDatePrototypeGetFullYear:
594 : case Builtins::kDatePrototypeGetHours:
595 : case Builtins::kDatePrototypeGetMilliseconds:
596 : case Builtins::kDatePrototypeGetMinutes:
597 : case Builtins::kDatePrototypeGetMonth:
598 : case Builtins::kDatePrototypeGetSeconds:
599 : case Builtins::kDatePrototypeGetTime:
600 : case Builtins::kDatePrototypeGetTimezoneOffset:
601 : case Builtins::kDatePrototypeGetUTCDate:
602 : case Builtins::kDatePrototypeGetUTCDay:
603 : case Builtins::kDatePrototypeGetUTCFullYear:
604 : case Builtins::kDatePrototypeGetUTCHours:
605 : case Builtins::kDatePrototypeGetUTCMilliseconds:
606 : case Builtins::kDatePrototypeGetUTCMinutes:
607 : case Builtins::kDatePrototypeGetUTCMonth:
608 : case Builtins::kDatePrototypeGetUTCSeconds:
609 : case Builtins::kDatePrototypeGetYear:
610 : case Builtins::kDatePrototypeToDateString:
611 : case Builtins::kDatePrototypeToISOString:
612 : case Builtins::kDatePrototypeToUTCString:
613 : case Builtins::kDatePrototypeToString:
614 : #ifdef V8_INTL_SUPPORT
615 : case Builtins::kDatePrototypeToLocaleString:
616 : case Builtins::kDatePrototypeToLocaleDateString:
617 : case Builtins::kDatePrototypeToLocaleTimeString:
618 : #endif
619 : case Builtins::kDatePrototypeToTimeString:
620 : case Builtins::kDatePrototypeToJson:
621 : case Builtins::kDatePrototypeToPrimitive:
622 : case Builtins::kDatePrototypeValueOf:
623 : // Map builtins.
624 : case Builtins::kMapConstructor:
625 : case Builtins::kMapPrototypeForEach:
626 : case Builtins::kMapPrototypeGet:
627 : case Builtins::kMapPrototypeHas:
628 : case Builtins::kMapPrototypeEntries:
629 : case Builtins::kMapPrototypeGetSize:
630 : case Builtins::kMapPrototypeKeys:
631 : case Builtins::kMapPrototypeValues:
632 : // WeakMap builtins.
633 : case Builtins::kWeakMapConstructor:
634 : case Builtins::kWeakMapGet:
635 : case Builtins::kWeakMapPrototypeHas:
636 : // Math builtins.
637 : case Builtins::kMathAbs:
638 : case Builtins::kMathAcos:
639 : case Builtins::kMathAcosh:
640 : case Builtins::kMathAsin:
641 : case Builtins::kMathAsinh:
642 : case Builtins::kMathAtan:
643 : case Builtins::kMathAtanh:
644 : case Builtins::kMathAtan2:
645 : case Builtins::kMathCeil:
646 : case Builtins::kMathCbrt:
647 : case Builtins::kMathExpm1:
648 : case Builtins::kMathClz32:
649 : case Builtins::kMathCos:
650 : case Builtins::kMathCosh:
651 : case Builtins::kMathExp:
652 : case Builtins::kMathFloor:
653 : case Builtins::kMathFround:
654 : case Builtins::kMathHypot:
655 : case Builtins::kMathImul:
656 : case Builtins::kMathLog:
657 : case Builtins::kMathLog1p:
658 : case Builtins::kMathLog2:
659 : case Builtins::kMathLog10:
660 : case Builtins::kMathMax:
661 : case Builtins::kMathMin:
662 : case Builtins::kMathPow:
663 : case Builtins::kMathRandom:
664 : case Builtins::kMathRound:
665 : case Builtins::kMathSign:
666 : case Builtins::kMathSin:
667 : case Builtins::kMathSinh:
668 : case Builtins::kMathSqrt:
669 : case Builtins::kMathTan:
670 : case Builtins::kMathTanh:
671 : case Builtins::kMathTrunc:
672 : // Number builtins.
673 : case Builtins::kNumberConstructor:
674 : case Builtins::kNumberIsFinite:
675 : case Builtins::kNumberIsInteger:
676 : case Builtins::kNumberIsNaN:
677 : case Builtins::kNumberIsSafeInteger:
678 : case Builtins::kNumberParseFloat:
679 : case Builtins::kNumberParseInt:
680 : case Builtins::kNumberPrototypeToExponential:
681 : case Builtins::kNumberPrototypeToFixed:
682 : case Builtins::kNumberPrototypeToPrecision:
683 : case Builtins::kNumberPrototypeToString:
684 : case Builtins::kNumberPrototypeToLocaleString:
685 : case Builtins::kNumberPrototypeValueOf:
686 : // BigInt builtins.
687 : case Builtins::kBigIntConstructor:
688 : case Builtins::kBigIntAsIntN:
689 : case Builtins::kBigIntAsUintN:
690 : case Builtins::kBigIntPrototypeToString:
691 : case Builtins::kBigIntPrototypeValueOf:
692 : // Set builtins.
693 : case Builtins::kSetConstructor:
694 : case Builtins::kSetPrototypeEntries:
695 : case Builtins::kSetPrototypeForEach:
696 : case Builtins::kSetPrototypeGetSize:
697 : case Builtins::kSetPrototypeHas:
698 : case Builtins::kSetPrototypeValues:
699 : // WeakSet builtins.
700 : case Builtins::kWeakSetConstructor:
701 : case Builtins::kWeakSetPrototypeHas:
702 : // String builtins. Strings are immutable.
703 : case Builtins::kStringFromCharCode:
704 : case Builtins::kStringFromCodePoint:
705 : case Builtins::kStringConstructor:
706 : case Builtins::kStringPrototypeAnchor:
707 : case Builtins::kStringPrototypeBig:
708 : case Builtins::kStringPrototypeBlink:
709 : case Builtins::kStringPrototypeBold:
710 : case Builtins::kStringPrototypeCharAt:
711 : case Builtins::kStringPrototypeCharCodeAt:
712 : case Builtins::kStringPrototypeCodePointAt:
713 : case Builtins::kStringPrototypeConcat:
714 : case Builtins::kStringPrototypeEndsWith:
715 : case Builtins::kStringPrototypeFixed:
716 : case Builtins::kStringPrototypeFontcolor:
717 : case Builtins::kStringPrototypeFontsize:
718 : case Builtins::kStringPrototypeIncludes:
719 : case Builtins::kStringPrototypeIndexOf:
720 : case Builtins::kStringPrototypeItalics:
721 : case Builtins::kStringPrototypeLastIndexOf:
722 : case Builtins::kStringPrototypeLink:
723 : case Builtins::kStringPrototypeMatchAll:
724 : case Builtins::kStringPrototypePadEnd:
725 : case Builtins::kStringPrototypePadStart:
726 : case Builtins::kStringPrototypeRepeat:
727 : case Builtins::kStringPrototypeSlice:
728 : case Builtins::kStringPrototypeSmall:
729 : case Builtins::kStringPrototypeStartsWith:
730 : case Builtins::kStringPrototypeStrike:
731 : case Builtins::kStringPrototypeSub:
732 : case Builtins::kStringPrototypeSubstr:
733 : case Builtins::kStringPrototypeSubstring:
734 : case Builtins::kStringPrototypeSup:
735 : case Builtins::kStringPrototypeToString:
736 : #ifndef V8_INTL_SUPPORT
737 : case Builtins::kStringPrototypeToLowerCase:
738 : case Builtins::kStringPrototypeToUpperCase:
739 : #endif
740 : case Builtins::kStringPrototypeTrim:
741 : case Builtins::kStringPrototypeTrimEnd:
742 : case Builtins::kStringPrototypeTrimStart:
743 : case Builtins::kStringPrototypeValueOf:
744 : case Builtins::kStringToNumber:
745 : case Builtins::kStringSubstring:
746 : // Symbol builtins.
747 : case Builtins::kSymbolConstructor:
748 : case Builtins::kSymbolKeyFor:
749 : case Builtins::kSymbolPrototypeToString:
750 : case Builtins::kSymbolPrototypeValueOf:
751 : case Builtins::kSymbolPrototypeToPrimitive:
752 : // JSON builtins.
753 : case Builtins::kJsonParse:
754 : case Builtins::kJsonStringify:
755 : // Global function builtins.
756 : case Builtins::kGlobalDecodeURI:
757 : case Builtins::kGlobalDecodeURIComponent:
758 : case Builtins::kGlobalEncodeURI:
759 : case Builtins::kGlobalEncodeURIComponent:
760 : case Builtins::kGlobalEscape:
761 : case Builtins::kGlobalUnescape:
762 : case Builtins::kGlobalIsFinite:
763 : case Builtins::kGlobalIsNaN:
764 : // Function builtins.
765 : case Builtins::kFunctionPrototypeToString:
766 : case Builtins::kFunctionPrototypeBind:
767 : case Builtins::kFastFunctionPrototypeBind:
768 : case Builtins::kFunctionPrototypeCall:
769 : case Builtins::kFunctionPrototypeApply:
770 : // Error builtins.
771 : case Builtins::kErrorConstructor:
772 : case Builtins::kMakeError:
773 : case Builtins::kMakeTypeError:
774 : case Builtins::kMakeSyntaxError:
775 : case Builtins::kMakeRangeError:
776 : case Builtins::kMakeURIError:
777 : // RegExp builtins.
778 : case Builtins::kRegExpConstructor:
779 : // Internal.
780 : case Builtins::kStrictPoisonPillThrower:
781 : case Builtins::kAllocateInYoungGeneration:
782 : case Builtins::kAllocateInOldGeneration:
783 : return DebugInfo::kHasNoSideEffect;
784 :
785 : // Set builtins.
786 : case Builtins::kSetIteratorPrototypeNext:
787 : case Builtins::kSetPrototypeAdd:
788 : case Builtins::kSetPrototypeClear:
789 : case Builtins::kSetPrototypeDelete:
790 : // Array builtins.
791 : case Builtins::kArrayIteratorPrototypeNext:
792 : case Builtins::kArrayPrototypePop:
793 : case Builtins::kArrayPrototypePush:
794 : case Builtins::kArrayPrototypeReverse:
795 : case Builtins::kArrayPrototypeShift:
796 : case Builtins::kArrayPrototypeUnshift:
797 : case Builtins::kArrayPrototypeSplice:
798 : case Builtins::kArrayUnshift:
799 : // Map builtins.
800 : case Builtins::kMapIteratorPrototypeNext:
801 : case Builtins::kMapPrototypeClear:
802 : case Builtins::kMapPrototypeDelete:
803 : case Builtins::kMapPrototypeSet:
804 : // RegExp builtins.
805 : case Builtins::kRegExpPrototypeTest:
806 : case Builtins::kRegExpPrototypeExec:
807 : case Builtins::kRegExpPrototypeSplit:
808 : case Builtins::kRegExpPrototypeFlagsGetter:
809 : case Builtins::kRegExpPrototypeGlobalGetter:
810 : case Builtins::kRegExpPrototypeIgnoreCaseGetter:
811 : case Builtins::kRegExpPrototypeMatchAll:
812 : case Builtins::kRegExpPrototypeMultilineGetter:
813 : case Builtins::kRegExpPrototypeDotAllGetter:
814 : case Builtins::kRegExpPrototypeUnicodeGetter:
815 : case Builtins::kRegExpPrototypeStickyGetter:
816 427 : return DebugInfo::kRequiresRuntimeChecks;
817 : default:
818 2012 : if (FLAG_trace_side_effect_free_debug_evaluate) {
819 0 : PrintF("[debug-evaluate] built-in %s may cause side effect.\n",
820 0 : Builtins::name(id));
821 : }
822 : return DebugInfo::kHasSideEffects;
823 : }
824 : }
825 :
826 : bool BytecodeRequiresRuntimeCheck(interpreter::Bytecode bytecode) {
827 : using interpreter::Bytecode;
828 : switch (bytecode) {
829 : case Bytecode::kStaNamedProperty:
830 : case Bytecode::kStaNamedPropertyNoFeedback:
831 : case Bytecode::kStaNamedOwnProperty:
832 : case Bytecode::kStaKeyedProperty:
833 : case Bytecode::kStaInArrayLiteral:
834 : case Bytecode::kStaDataPropertyInLiteral:
835 : case Bytecode::kStaCurrentContextSlot:
836 : return true;
837 : default:
838 : return false;
839 : }
840 : }
841 :
842 : } // anonymous namespace
843 :
844 : // static
845 12255 : DebugInfo::SideEffectState DebugEvaluate::FunctionGetSideEffectState(
846 : Isolate* isolate, Handle<SharedFunctionInfo> info) {
847 12255 : if (FLAG_trace_side_effect_free_debug_evaluate) {
848 : PrintF("[debug-evaluate] Checking function %s for side effect.\n",
849 0 : info->DebugName()->ToCString().get());
850 : }
851 :
852 : DCHECK(info->is_compiled());
853 12255 : if (info->HasBytecodeArray()) {
854 : // Check bytecodes against whitelist.
855 11492 : Handle<BytecodeArray> bytecode_array(info->GetBytecodeArray(), isolate);
856 5746 : if (FLAG_trace_side_effect_free_debug_evaluate) {
857 0 : bytecode_array->Print();
858 : }
859 : bool requires_runtime_checks = false;
860 79261 : for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done();
861 73515 : it.Advance()) {
862 73668 : interpreter::Bytecode bytecode = it.current_bytecode();
863 :
864 73668 : if (interpreter::Bytecodes::IsCallRuntime(bytecode)) {
865 : Runtime::FunctionId id =
866 : (bytecode == interpreter::Bytecode::kInvokeIntrinsic)
867 : ? it.GetIntrinsicIdOperand(0)
868 1328 : : it.GetRuntimeIdOperand(0);
869 1328 : if (IntrinsicHasNoSideEffect(id)) continue;
870 153 : return DebugInfo::kHasSideEffects;
871 : }
872 :
873 72340 : if (BytecodeHasNoSideEffect(bytecode)) continue;
874 2446 : if (BytecodeRequiresRuntimeCheck(bytecode)) {
875 : requires_runtime_checks = true;
876 : continue;
877 : }
878 :
879 90 : if (FLAG_trace_side_effect_free_debug_evaluate) {
880 0 : PrintF("[debug-evaluate] bytecode %s may cause side effect.\n",
881 0 : interpreter::Bytecodes::ToString(bytecode));
882 : }
883 :
884 : // Did not match whitelist.
885 : return DebugInfo::kHasSideEffects;
886 : }
887 : return requires_runtime_checks ? DebugInfo::kRequiresRuntimeChecks
888 5593 : : DebugInfo::kHasNoSideEffect;
889 6509 : } else if (info->IsApiFunction()) {
890 316 : if (info->GetCode()->is_builtin()) {
891 316 : return info->GetCode()->builtin_index() == Builtins::kHandleApiCall
892 : ? DebugInfo::kHasNoSideEffect
893 158 : : DebugInfo::kHasSideEffects;
894 : }
895 : } else {
896 : // Check built-ins against whitelist.
897 : int builtin_index =
898 6351 : info->HasBuiltinId() ? info->builtin_id() : Builtins::kNoBuiltinId;
899 6351 : if (!Builtins::IsBuiltinId(builtin_index))
900 : return DebugInfo::kHasSideEffects;
901 : DebugInfo::SideEffectState state =
902 6351 : BuiltinGetSideEffectState(static_cast<Builtins::Name>(builtin_index));
903 6351 : return state;
904 : }
905 :
906 : return DebugInfo::kHasSideEffects;
907 : }
908 :
909 : #ifdef DEBUG
910 : static bool TransitivelyCalledBuiltinHasNoSideEffect(Builtins::Name caller,
911 : Builtins::Name callee) {
912 : switch (callee) {
913 : // Transitively called Builtins:
914 : case Builtins::kAbort:
915 : case Builtins::kAbortJS:
916 : case Builtins::kAdaptorWithBuiltinExitFrame:
917 : case Builtins::kArrayConstructorImpl:
918 : case Builtins::kArrayEveryLoopContinuation:
919 : case Builtins::kArrayFilterLoopContinuation:
920 : case Builtins::kArrayFindIndexLoopContinuation:
921 : case Builtins::kArrayFindLoopContinuation:
922 : case Builtins::kArrayForEachLoopContinuation:
923 : case Builtins::kArrayIncludesHoleyDoubles:
924 : case Builtins::kArrayIncludesPackedDoubles:
925 : case Builtins::kArrayIncludesSmiOrObject:
926 : case Builtins::kArrayIndexOfHoleyDoubles:
927 : case Builtins::kArrayIndexOfPackedDoubles:
928 : case Builtins::kArrayIndexOfSmiOrObject:
929 : case Builtins::kArrayMapLoopContinuation:
930 : case Builtins::kArrayReduceLoopContinuation:
931 : case Builtins::kArrayReduceRightLoopContinuation:
932 : case Builtins::kArraySomeLoopContinuation:
933 : case Builtins::kArrayTimSort:
934 : case Builtins::kCall_ReceiverIsAny:
935 : case Builtins::kCall_ReceiverIsNullOrUndefined:
936 : case Builtins::kCallWithArrayLike:
937 : case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit:
938 : case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit:
939 : case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvInRegister_NoBuiltinExit:
940 : case Builtins::kCEntry_Return1_SaveFPRegs_ArgvOnStack_NoBuiltinExit:
941 : case Builtins::kCEntry_Return1_SaveFPRegs_ArgvOnStack_BuiltinExit:
942 : case Builtins::kCEntry_Return2_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit:
943 : case Builtins::kCEntry_Return2_DontSaveFPRegs_ArgvOnStack_BuiltinExit:
944 : case Builtins::kCEntry_Return2_DontSaveFPRegs_ArgvInRegister_NoBuiltinExit:
945 : case Builtins::kCEntry_Return2_SaveFPRegs_ArgvOnStack_NoBuiltinExit:
946 : case Builtins::kCEntry_Return2_SaveFPRegs_ArgvOnStack_BuiltinExit:
947 : case Builtins::kCloneFastJSArray:
948 : case Builtins::kConstruct:
949 : case Builtins::kConvertToLocaleString:
950 : case Builtins::kCreateTypedArray:
951 : case Builtins::kDirectCEntry:
952 : case Builtins::kDoubleToI:
953 : case Builtins::kExtractFastJSArray:
954 : case Builtins::kFastNewObject:
955 : case Builtins::kFindOrderedHashMapEntry:
956 : case Builtins::kFlatMapIntoArray:
957 : case Builtins::kFlattenIntoArray:
958 : case Builtins::kGetProperty:
959 : case Builtins::kHasProperty:
960 : case Builtins::kCreateHTML:
961 : case Builtins::kNonNumberToNumber:
962 : case Builtins::kNonPrimitiveToPrimitive_Number:
963 : case Builtins::kNumberToString:
964 : case Builtins::kObjectToString:
965 : case Builtins::kOrderedHashTableHealIndex:
966 : case Builtins::kOrdinaryToPrimitive_Number:
967 : case Builtins::kOrdinaryToPrimitive_String:
968 : case Builtins::kParseInt:
969 : case Builtins::kProxyHasProperty:
970 : case Builtins::kRecordWrite:
971 : case Builtins::kStringAdd_CheckNone:
972 : case Builtins::kStringEqual:
973 : case Builtins::kStringIndexOf:
974 : case Builtins::kStringRepeat:
975 : case Builtins::kToInteger:
976 : case Builtins::kToInteger_TruncateMinusZero:
977 : case Builtins::kToLength:
978 : case Builtins::kToName:
979 : case Builtins::kToObject:
980 : case Builtins::kToString:
981 : case Builtins::kWeakMapLookupHashIndex:
982 : return true;
983 : case Builtins::kJoinStackPop:
984 : case Builtins::kJoinStackPush:
985 : switch (caller) {
986 : case Builtins::kArrayPrototypeJoin:
987 : case Builtins::kArrayPrototypeToLocaleString:
988 : case Builtins::kTypedArrayPrototypeJoin:
989 : case Builtins::kTypedArrayPrototypeToLocaleString:
990 : return true;
991 : default:
992 : return false;
993 : }
994 : case Builtins::kFastCreateDataProperty:
995 : switch (caller) {
996 : case Builtins::kArrayPrototypeSlice:
997 : case Builtins::kArrayFilter:
998 : return true;
999 : default:
1000 : return false;
1001 : }
1002 : case Builtins::kSetProperty:
1003 : switch (caller) {
1004 : case Builtins::kArrayPrototypeSlice:
1005 : case Builtins::kTypedArrayPrototypeMap:
1006 : case Builtins::kStringPrototypeMatchAll:
1007 : return true;
1008 : default:
1009 : return false;
1010 : }
1011 : default:
1012 : return false;
1013 : }
1014 : }
1015 :
1016 : // static
1017 : void DebugEvaluate::VerifyTransitiveBuiltins(Isolate* isolate) {
1018 : // TODO(yangguo): also check runtime calls.
1019 : bool failed = false;
1020 : bool sanity_check = false;
1021 : for (int i = 0; i < Builtins::builtin_count; i++) {
1022 : Builtins::Name caller = static_cast<Builtins::Name>(i);
1023 : DebugInfo::SideEffectState state = BuiltinGetSideEffectState(caller);
1024 : if (state != DebugInfo::kHasNoSideEffect) continue;
1025 : Code code = isolate->builtins()->builtin(caller);
1026 : int mode = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
1027 : RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET);
1028 :
1029 : for (RelocIterator it(code, mode); !it.done(); it.next()) {
1030 : RelocInfo* rinfo = it.rinfo();
1031 : DCHECK(RelocInfo::IsCodeTargetMode(rinfo->rmode()));
1032 : Code callee_code = isolate->heap()->GcSafeFindCodeForInnerPointer(
1033 : rinfo->target_address());
1034 : if (!callee_code->is_builtin()) continue;
1035 : Builtins::Name callee =
1036 : static_cast<Builtins::Name>(callee_code->builtin_index());
1037 : if (BuiltinGetSideEffectState(callee) == DebugInfo::kHasNoSideEffect) {
1038 : continue;
1039 : }
1040 : if (TransitivelyCalledBuiltinHasNoSideEffect(caller, callee)) {
1041 : sanity_check = true;
1042 : continue;
1043 : }
1044 : PrintF("Whitelisted builtin %s calls non-whitelisted builtin %s\n",
1045 : Builtins::name(caller), Builtins::name(callee));
1046 : failed = true;
1047 : }
1048 : }
1049 : CHECK(!failed);
1050 : #if defined(V8_TARGET_ARCH_PPC) || defined(V8_TARGET_ARCH_MIPS64)
1051 : // Isolate-independent builtin calls and jumps do not emit reloc infos
1052 : // on PPC. We try to avoid using PC relative code due to performance
1053 : // issue with especially older hardwares.
1054 : // MIPS64 doesn't have PC relative code currently.
1055 : // TODO(mips): Add PC relative code to MIPS64.
1056 : USE(sanity_check);
1057 : #else
1058 : CHECK(sanity_check);
1059 : #endif
1060 : }
1061 : #endif // DEBUG
1062 :
1063 : // static
1064 6759 : void DebugEvaluate::ApplySideEffectChecks(
1065 : Handle<BytecodeArray> bytecode_array) {
1066 142771 : for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done();
1067 136012 : it.Advance()) {
1068 136012 : interpreter::Bytecode bytecode = it.current_bytecode();
1069 136012 : if (BytecodeRequiresRuntimeCheck(bytecode)) it.ApplyDebugBreak();
1070 : }
1071 6759 : }
1072 :
1073 : } // namespace internal
1074 122036 : } // namespace v8
|