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