blob: 0259f01ccc2123a53b760f8954ba2efb63769482 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004
5#ifndef V8_DEOPTIMIZER_H_
6#define V8_DEOPTIMIZER_H_
7
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/allocation.h"
9#include "src/macro-assembler.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010010
11
12namespace v8 {
13namespace internal {
14
15class FrameDescription;
16class TranslationIterator;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000017class DeoptimizedFrameInfo;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018class TranslatedState;
19class RegisterValues;
Ben Murdochb0fe1622011-05-05 13:52:32 +010020
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021class TranslatedValue {
Ben Murdochb0fe1622011-05-05 13:52:32 +010022 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023 // Allocation-less getter of the value.
24 // Returns heap()->arguments_marker() if allocation would be
25 // necessary to get the value.
26 Object* GetRawValue() const;
27 Handle<Object> GetValue();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029 bool IsMaterializedObject() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +010030 bool IsMaterializableByDebugger() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031
32 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033 friend class TranslatedState;
34 friend class TranslatedFrame;
35
36 enum Kind {
37 kInvalid,
38 kTagged,
39 kInt32,
40 kUInt32,
41 kBoolBit,
42 kDouble,
43 kCapturedObject, // Object captured by the escape analysis.
44 // The number of nested objects can be obtained
45 // with the DeferredObjectLength() method
46 // (the values of the nested objects follow
47 // this value in the depth-first order.)
48 kDuplicatedObject, // Duplicated object of a deferred object.
49 kArgumentsObject // Arguments object - only used to keep indexing
50 // in sync, it should not be materialized.
51 };
52
53 TranslatedValue(TranslatedState* container, Kind kind)
54 : kind_(kind), container_(container) {}
55 Kind kind() const { return kind_; }
56 void Handlify();
57 int GetChildrenCount() const;
58
59 static TranslatedValue NewArgumentsObject(TranslatedState* container,
60 int length, int object_index);
61 static TranslatedValue NewDeferredObject(TranslatedState* container,
62 int length, int object_index);
63 static TranslatedValue NewDuplicateObject(TranslatedState* container, int id);
64 static TranslatedValue NewDouble(TranslatedState* container, double value);
65 static TranslatedValue NewInt32(TranslatedState* container, int32_t value);
66 static TranslatedValue NewUInt32(TranslatedState* container, uint32_t value);
67 static TranslatedValue NewBool(TranslatedState* container, uint32_t value);
68 static TranslatedValue NewTagged(TranslatedState* container, Object* literal);
69 static TranslatedValue NewInvalid(TranslatedState* container);
70
71 Isolate* isolate() const;
72 void MaterializeSimple();
73
74 Kind kind_;
75 TranslatedState* container_; // This is only needed for materialization of
76 // objects and constructing handles (to get
77 // to the isolate).
78
79 MaybeHandle<Object> value_; // Before handlification, this is always null,
80 // after materialization it is never null,
81 // in between it is only null if the value needs
82 // to be materialized.
83
84 struct MaterializedObjectInfo {
85 int id_;
86 int length_; // Applies only to kArgumentsObject or kCapturedObject kinds.
87 };
88
89 union {
90 // kind kTagged. After handlification it is always nullptr.
91 Object* raw_literal_;
92 // kind is kUInt32 or kBoolBit.
93 uint32_t uint32_value_;
94 // kind is kInt32.
95 int32_t int32_value_;
96 // kind is kDouble
97 double double_value_;
98 // kind is kDuplicatedObject or kArgumentsObject or kCapturedObject.
99 MaterializedObjectInfo materialization_info_;
100 };
101
102 // Checked accessors for the union members.
103 Object* raw_literal() const;
104 int32_t int32_value() const;
105 uint32_t uint32_value() const;
106 double double_value() const;
107 int object_length() const;
108 int object_index() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000109};
110
111
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112class TranslatedFrame {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000113 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000114 enum Kind {
115 kFunction,
116 kInterpretedFunction,
117 kGetter,
118 kSetter,
119 kArgumentsAdaptor,
120 kConstructStub,
121 kCompiledStub,
122 kInvalid
123 };
Ben Murdoch8b112d22011-06-08 16:22:53 +0100124
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 int GetValueCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000126
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000127 Kind kind() const { return kind_; }
128 BailoutId node_id() const { return node_id_; }
129 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
130 int height() const { return height_; }
131
Ben Murdoch097c5b22016-05-18 11:27:45 +0100132 SharedFunctionInfo* raw_shared_info() const {
133 CHECK_NOT_NULL(raw_shared_info_);
134 return raw_shared_info_;
135 }
136
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000137 class iterator {
138 public:
139 iterator& operator++() {
140 AdvanceIterator(&position_);
141 return *this;
142 }
143
144 iterator operator++(int) {
145 iterator original(position_);
146 AdvanceIterator(&position_);
147 return original;
148 }
149
150 bool operator==(const iterator& other) const {
151 return position_ == other.position_;
152 }
153 bool operator!=(const iterator& other) const { return !(*this == other); }
154
155 TranslatedValue& operator*() { return (*position_); }
156 TranslatedValue* operator->() { return &(*position_); }
157
158 private:
159 friend TranslatedFrame;
160
161 explicit iterator(std::deque<TranslatedValue>::iterator position)
162 : position_(position) {}
163
164 std::deque<TranslatedValue>::iterator position_;
165 };
166
167 typedef TranslatedValue& reference;
168 typedef TranslatedValue const& const_reference;
169
170 iterator begin() { return iterator(values_.begin()); }
171 iterator end() { return iterator(values_.end()); }
172
173 reference front() { return values_.front(); }
174 const_reference front() const { return values_.front(); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100175
176 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000177 friend class TranslatedState;
178
179 // Constructor static methods.
180 static TranslatedFrame JSFrame(BailoutId node_id,
181 SharedFunctionInfo* shared_info, int height);
182 static TranslatedFrame InterpretedFrame(BailoutId bytecode_offset,
183 SharedFunctionInfo* shared_info,
184 int height);
185 static TranslatedFrame AccessorFrame(Kind kind,
186 SharedFunctionInfo* shared_info);
187 static TranslatedFrame ArgumentsAdaptorFrame(SharedFunctionInfo* shared_info,
188 int height);
189 static TranslatedFrame ConstructStubFrame(SharedFunctionInfo* shared_info,
190 int height);
191 static TranslatedFrame CompiledStubFrame(int height, Isolate* isolate) {
192 return TranslatedFrame(kCompiledStub, isolate, nullptr, height);
193 }
194 static TranslatedFrame InvalidFrame() {
195 return TranslatedFrame(kInvalid, nullptr);
196 }
197
198 static void AdvanceIterator(std::deque<TranslatedValue>::iterator* iter);
199
200 TranslatedFrame(Kind kind, Isolate* isolate,
201 SharedFunctionInfo* shared_info = nullptr, int height = 0)
202 : kind_(kind),
203 node_id_(BailoutId::None()),
204 raw_shared_info_(shared_info),
205 height_(height),
206 isolate_(isolate) {}
207
208
209 void Add(const TranslatedValue& value) { values_.push_back(value); }
210 void Handlify();
211
212 Kind kind_;
213 BailoutId node_id_;
214 SharedFunctionInfo* raw_shared_info_;
215 Handle<SharedFunctionInfo> shared_info_;
216 int height_;
217 Isolate* isolate_;
218
219 typedef std::deque<TranslatedValue> ValuesContainer;
220
221 ValuesContainer values_;
222};
223
224
225// Auxiliary class for translating deoptimization values.
226// Typical usage sequence:
227//
228// 1. Construct the instance. This will involve reading out the translations
229// and resolving them to values using the supplied frame pointer and
230// machine state (registers). This phase is guaranteed not to allocate
231// and not to use any HandleScope. Any object pointers will be stored raw.
232//
233// 2. Handlify pointers. This will convert all the raw pointers to handles.
234//
235// 3. Reading out the frame values.
236//
237// Note: After the instance is constructed, it is possible to iterate over
238// the values eagerly.
239
240class TranslatedState {
241 public:
242 TranslatedState();
243 explicit TranslatedState(JavaScriptFrame* frame);
244
245 void Prepare(bool has_adapted_arguments, Address stack_frame_pointer);
246
247 // Store newly materialized values into the isolate.
248 void StoreMaterializedValuesAndDeopt();
249
250 typedef std::vector<TranslatedFrame>::iterator iterator;
251 iterator begin() { return frames_.begin(); }
252 iterator end() { return frames_.end(); }
253
254 typedef std::vector<TranslatedFrame>::const_iterator const_iterator;
255 const_iterator begin() const { return frames_.begin(); }
256 const_iterator end() const { return frames_.end(); }
257
258 std::vector<TranslatedFrame>& frames() { return frames_; }
259
260 TranslatedFrame* GetArgumentsInfoFromJSFrameIndex(int jsframe_index,
261 int* arguments_count);
262
263 Isolate* isolate() { return isolate_; }
264
265 void Init(Address input_frame_pointer, TranslationIterator* iterator,
266 FixedArray* literal_array, RegisterValues* registers,
267 FILE* trace_file);
268
269 private:
270 friend TranslatedValue;
271
272 TranslatedFrame CreateNextTranslatedFrame(TranslationIterator* iterator,
273 FixedArray* literal_array,
274 Address fp,
275 FILE* trace_file);
276 TranslatedValue CreateNextTranslatedValue(int frame_index, int value_index,
277 TranslationIterator* iterator,
278 FixedArray* literal_array,
279 Address fp,
280 RegisterValues* registers,
281 FILE* trace_file);
282
283 void UpdateFromPreviouslyMaterializedObjects();
284 Handle<Object> MaterializeAt(int frame_index, int* value_index);
285 Handle<Object> MaterializeObjectAt(int object_index);
286 bool GetAdaptedArguments(Handle<JSObject>* result, int frame_index);
287
288 static uint32_t GetUInt32Slot(Address fp, int slot_index);
289
290 std::vector<TranslatedFrame> frames_;
291 Isolate* isolate_;
292 Address stack_frame_pointer_;
293 bool has_adapted_arguments_;
294
295 struct ObjectPosition {
296 int frame_index_;
297 int value_index_;
298 };
299 std::deque<ObjectPosition> object_positions_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100300};
301
302
303class OptimizedFunctionVisitor BASE_EMBEDDED {
304 public:
305 virtual ~OptimizedFunctionVisitor() {}
306
307 // Function which is called before iteration of any optimized functions
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308 // from given native context.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100309 virtual void EnterContext(Context* context) = 0;
310
311 virtual void VisitFunction(JSFunction* function) = 0;
312
313 // Function which is called after iteration of all optimized functions
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000314 // from given native context.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100315 virtual void LeaveContext(Context* context) = 0;
316};
317
318
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000319#define DEOPT_MESSAGES_LIST(V) \
320 V(kAccessCheck, "Access check needed") \
321 V(kNoReason, "no reason") \
322 V(kConstantGlobalVariableAssignment, "Constant global variable assignment") \
323 V(kConversionOverflow, "conversion overflow") \
324 V(kDivisionByZero, "division by zero") \
325 V(kElementsKindUnhandledInKeyedLoadGenericStub, \
326 "ElementsKind unhandled in KeyedLoadGenericStub") \
327 V(kExpectedHeapNumber, "Expected heap number") \
328 V(kExpectedSmi, "Expected smi") \
329 V(kForcedDeoptToRuntime, "Forced deopt to runtime") \
330 V(kHole, "hole") \
331 V(kHoleyArrayDespitePackedElements_kindFeedback, \
332 "Holey array despite packed elements_kind feedback") \
333 V(kInstanceMigrationFailed, "instance migration failed") \
334 V(kInsufficientTypeFeedbackForCallWithArguments, \
335 "Insufficient type feedback for call with arguments") \
336 V(kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation, \
337 "Insufficient type feedback for combined type of binary operation") \
338 V(kInsufficientTypeFeedbackForGenericNamedAccess, \
339 "Insufficient type feedback for generic named access") \
340 V(kInsufficientTypeFeedbackForKeyedLoad, \
341 "Insufficient type feedback for keyed load") \
342 V(kInsufficientTypeFeedbackForKeyedStore, \
343 "Insufficient type feedback for keyed store") \
344 V(kInsufficientTypeFeedbackForLHSOfBinaryOperation, \
345 "Insufficient type feedback for LHS of binary operation") \
346 V(kInsufficientTypeFeedbackForRHSOfBinaryOperation, \
347 "Insufficient type feedback for RHS of binary operation") \
348 V(kKeyIsNegative, "key is negative") \
349 V(kLiteralsWereDisposed, "literals have been disposed") \
350 V(kLostPrecision, "lost precision") \
351 V(kLostPrecisionOrNaN, "lost precision or NaN") \
352 V(kMementoFound, "memento found") \
353 V(kMinusZero, "minus zero") \
354 V(kNaN, "NaN") \
355 V(kNegativeKeyEncountered, "Negative key encountered") \
356 V(kNegativeValue, "negative value") \
357 V(kNoCache, "no cache") \
358 V(kNonStrictElementsInKeyedLoadGenericStub, \
359 "non-strict elements in KeyedLoadGenericStub") \
360 V(kNotADateObject, "not a date object") \
361 V(kNotAHeapNumber, "not a heap number") \
362 V(kNotAHeapNumberUndefinedBoolean, "not a heap number/undefined/true/false") \
363 V(kNotAHeapNumberUndefined, "not a heap number/undefined") \
364 V(kNotAJavaScriptObject, "not a JavaScript object") \
365 V(kNotASmi, "not a Smi") \
366 V(kNull, "null") \
367 V(kOutOfBounds, "out of bounds") \
368 V(kOutsideOfRange, "Outside of range") \
369 V(kOverflow, "overflow") \
370 V(kProxy, "proxy") \
371 V(kReceiverWasAGlobalObject, "receiver was a global object") \
372 V(kSmi, "Smi") \
373 V(kTooManyArguments, "too many arguments") \
374 V(kTooManyUndetectableTypes, "Too many undetectable types") \
375 V(kTracingElementsTransitions, "Tracing elements transitions") \
376 V(kTypeMismatchBetweenFeedbackAndConstant, \
377 "Type mismatch between feedback and constant") \
378 V(kUndefined, "undefined") \
379 V(kUnexpectedCellContentsInConstantGlobalStore, \
380 "Unexpected cell contents in constant global store") \
381 V(kUnexpectedCellContentsInGlobalStore, \
382 "Unexpected cell contents in global store") \
383 V(kUnexpectedObject, "unexpected object") \
384 V(kUnexpectedRHSOfBinaryOperation, "Unexpected RHS of binary operation") \
385 V(kUninitializedBoilerplateInFastClone, \
386 "Uninitialized boilerplate in fast clone") \
387 V(kUninitializedBoilerplateLiterals, "Uninitialized boilerplate literals") \
388 V(kUnknownMapInPolymorphicAccess, "Unknown map in polymorphic access") \
389 V(kUnknownMapInPolymorphicCall, "Unknown map in polymorphic call") \
390 V(kUnknownMapInPolymorphicElementAccess, \
391 "Unknown map in polymorphic element access") \
392 V(kUnknownMap, "Unknown map") \
393 V(kValueMismatch, "value mismatch") \
394 V(kWrongInstanceType, "wrong instance type") \
395 V(kWrongMap, "wrong map") \
396 V(kUndefinedOrNullInForIn, "null or undefined in for-in") \
397 V(kUndefinedOrNullInToObject, "null or undefined in ToObject")
398
399
Ben Murdochb0fe1622011-05-05 13:52:32 +0100400class Deoptimizer : public Malloced {
401 public:
402 enum BailoutType {
403 EAGER,
404 LAZY,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000405 SOFT,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000406 // This last bailout type is not really a bailout, but used by the
407 // debugger to deoptimize stack frames to allow inspection.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000408 DEBUGGER,
409 kBailoutTypesWithCodeEntry = SOFT + 1
Ben Murdochb0fe1622011-05-05 13:52:32 +0100410 };
411
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412#define DEOPT_MESSAGES_CONSTANTS(C, T) C,
413 enum DeoptReason {
414 DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_CONSTANTS) kLastDeoptReason
415 };
416#undef DEOPT_MESSAGES_CONSTANTS
417 static const char* GetDeoptReason(DeoptReason deopt_reason);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000418
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419 struct DeoptInfo {
420 DeoptInfo(SourcePosition position, const char* m, DeoptReason d)
421 : position(position), mnemonic(m), deopt_reason(d), inlining_id(0) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000423 SourcePosition position;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000424 const char* mnemonic;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000425 DeoptReason deopt_reason;
426 int inlining_id;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427 };
428
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000429 static DeoptInfo GetDeoptInfo(Code* code, byte* from);
430
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000431 struct JumpTableEntry : public ZoneObject {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000432 inline JumpTableEntry(Address entry, const DeoptInfo& deopt_info,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433 Deoptimizer::BailoutType type, bool frame)
434 : label(),
435 address(entry),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000436 deopt_info(deopt_info),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000437 bailout_type(type),
438 needs_frame(frame) {}
439
440 bool IsEquivalentTo(const JumpTableEntry& other) const {
441 return address == other.address && bailout_type == other.bailout_type &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000442 needs_frame == other.needs_frame;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443 }
444
445 Label label;
446 Address address;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000447 DeoptInfo deopt_info;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000448 Deoptimizer::BailoutType bailout_type;
449 bool needs_frame;
450 };
451
452 static bool TraceEnabledFor(BailoutType deopt_type,
453 StackFrame::Type frame_type);
454 static const char* MessageFor(BailoutType type);
455
Ben Murdochb0fe1622011-05-05 13:52:32 +0100456 int output_count() const { return output_count_; }
457
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000458 Handle<JSFunction> function() const { return Handle<JSFunction>(function_); }
459 Handle<Code> compiled_code() const { return Handle<Code>(compiled_code_); }
460 BailoutType bailout_type() const { return bailout_type_; }
461
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100462 // Number of created JS frames. Not all created frames are necessarily JS.
463 int jsframe_count() const { return jsframe_count_; }
464
Ben Murdochb0fe1622011-05-05 13:52:32 +0100465 static Deoptimizer* New(JSFunction* function,
466 BailoutType type,
467 unsigned bailout_id,
468 Address from,
Steve Block44f0eee2011-05-26 01:26:41 +0100469 int fp_to_sp_delta,
470 Isolate* isolate);
471 static Deoptimizer* Grab(Isolate* isolate);
472
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000473 // The returned object with information on the optimized frame needs to be
474 // freed before another one can be generated.
475 static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100476 int jsframe_index,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000477 Isolate* isolate);
478 static void DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
479 Isolate* isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000480
Steve Block44f0eee2011-05-26 01:26:41 +0100481 // Makes sure that there is enough room in the relocation
482 // information of a code object to perform lazy deoptimization
483 // patching. If there is not enough room a new relocation
484 // information object is allocated and comments are added until it
485 // is big enough.
486 static void EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100487
488 // Deoptimize the function now. Its current optimized code will never be run
489 // again and any activations of the optimized code will get deoptimized when
490 // execution returns.
491 static void DeoptimizeFunction(JSFunction* function);
492
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000493 // Deoptimize all code in the given isolate.
494 static void DeoptimizeAll(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100495
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000496 // Deoptimizes all optimized code that has been previously marked
497 // (via code->set_marked_for_deoptimization) and unlinks all functions that
498 // refer to that code.
499 static void DeoptimizeMarkedCode(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100500
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000501 // Visit all the known optimized functions in a given isolate.
502 static void VisitAllOptimizedFunctions(
503 Isolate* isolate, OptimizedFunctionVisitor* visitor);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100504
Steve Block1e0659c2011-05-24 12:43:12 +0100505 // The size in bytes of the code required at a lazy deopt patch site.
506 static int patch_size();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100507
Ben Murdochb0fe1622011-05-05 13:52:32 +0100508 ~Deoptimizer();
509
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000510 void MaterializeHeapObjects(JavaScriptFrameIterator* it);
511
Ben Murdoch8b112d22011-06-08 16:22:53 +0100512 static void ComputeOutputFrames(Deoptimizer* deoptimizer);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100513
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000514
515 enum GetEntryMode {
516 CALCULATE_ENTRY_ADDRESS,
517 ENSURE_ENTRY_CODE
518 };
519
520
521 static Address GetDeoptimizationEntry(
522 Isolate* isolate,
523 int id,
524 BailoutType type,
525 GetEntryMode mode = ENSURE_ENTRY_CODE);
526 static int GetDeoptimizationId(Isolate* isolate,
527 Address addr,
528 BailoutType type);
Steve Block9fac8402011-05-12 15:51:54 +0100529 static int GetOutputInfo(DeoptimizationOutputData* data,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000530 BailoutId node_id,
Steve Block9fac8402011-05-12 15:51:54 +0100531 SharedFunctionInfo* shared);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100532
Ben Murdochb0fe1622011-05-05 13:52:32 +0100533 // Code generation support.
534 static int input_offset() { return OFFSET_OF(Deoptimizer, input_); }
535 static int output_count_offset() {
536 return OFFSET_OF(Deoptimizer, output_count_);
537 }
538 static int output_offset() { return OFFSET_OF(Deoptimizer, output_); }
539
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000540 static int has_alignment_padding_offset() {
541 return OFFSET_OF(Deoptimizer, has_alignment_padding_);
542 }
543
Steve Block44f0eee2011-05-26 01:26:41 +0100544 static int GetDeoptimizedCodeCount(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100545
546 static const int kNotDeoptimizationEntry = -1;
547
548 // Generators for the deoptimization entry code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 class TableEntryGenerator BASE_EMBEDDED {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100550 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000551 TableEntryGenerator(MacroAssembler* masm, BailoutType type, int count)
552 : masm_(masm), type_(type), count_(count) {}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100553
554 void Generate();
555
556 protected:
557 MacroAssembler* masm() const { return masm_; }
558 BailoutType type() const { return type_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000559 Isolate* isolate() const { return masm_->isolate(); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100560
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000561 void GeneratePrologue();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100562
563 private:
564 int count() const { return count_; }
565
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000566 MacroAssembler* masm_;
567 Deoptimizer::BailoutType type_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100568 int count_;
569 };
570
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100571 int ConvertJSFrameIndexToFrameIndex(int jsframe_index);
572
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573 static size_t GetMaxDeoptTableSize();
574
575 static void EnsureCodeForDeoptimizationEntry(Isolate* isolate,
576 BailoutType type,
577 int max_entry_id);
578
579 Isolate* isolate() const { return isolate_; }
580
Ben Murdochb0fe1622011-05-05 13:52:32 +0100581 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000582 static const int kMinNumberOfEntries = 64;
583 static const int kMaxNumberOfEntries = 16384;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100584
Steve Block44f0eee2011-05-26 01:26:41 +0100585 Deoptimizer(Isolate* isolate,
586 JSFunction* function,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100587 BailoutType type,
588 unsigned bailout_id,
589 Address from,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000590 int fp_to_sp_delta,
591 Code* optimized_code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592 Code* FindOptimizedCode(JSFunction* function, Code* optimized_code);
593 void PrintFunctionName();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100594 void DeleteFrameDescriptions();
595
596 void DoComputeOutputFrames();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100597 void DoComputeJSFrame(int frame_index, bool goto_catch_handler);
598 void DoComputeInterpretedFrame(int frame_index, bool goto_catch_handler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000599 void DoComputeArgumentsAdaptorFrame(int frame_index);
600 void DoComputeConstructStubFrame(int frame_index);
601 void DoComputeAccessorStubFrame(int frame_index, bool is_setter_stub_frame);
602 void DoComputeCompiledStubFrame(int frame_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000603
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000604 void WriteTranslatedValueToOutput(
605 TranslatedFrame::iterator* iterator, int* input_index, int frame_index,
606 unsigned output_offset, const char* debug_hint_string = nullptr,
607 Address output_address_for_materialization = nullptr);
608 void WriteValueToOutput(Object* value, int input_index, int frame_index,
609 unsigned output_offset,
610 const char* debug_hint_string);
611 void DebugPrintOutputSlot(intptr_t value, int frame_index,
612 unsigned output_offset,
613 const char* debug_hint_string);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100614
615 unsigned ComputeInputFrameSize() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100616 static unsigned ComputeJavascriptFixedSize(SharedFunctionInfo* shared);
617 static unsigned ComputeInterpretedFixedSize(SharedFunctionInfo* shared);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100618
Ben Murdoch097c5b22016-05-18 11:27:45 +0100619 static unsigned ComputeIncomingArgumentSize(SharedFunctionInfo* shared);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000620 static unsigned ComputeOutgoingArgumentSize(Code* code, unsigned bailout_id);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100621
622 Object* ComputeLiteral(int index) const;
623
Ben Murdochb0fe1622011-05-05 13:52:32 +0100624 static void GenerateDeoptimizationEntries(
625 MacroAssembler* masm, int count, BailoutType type);
626
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000627 // Marks all the code in the given context for deoptimization.
628 static void MarkAllCodeForContext(Context* native_context);
629
630 // Visit all the known optimized functions in a given context.
631 static void VisitAllOptimizedFunctionsForContext(
632 Context* context, OptimizedFunctionVisitor* visitor);
633
634 // Deoptimizes all code marked in the given context.
635 static void DeoptimizeMarkedCodeForContext(Context* native_context);
636
637 // Patch the given code so that it will deoptimize itself.
638 static void PatchCodeForDeoptimization(Isolate* isolate, Code* code);
639
640 // Searches the list of known deoptimizing code for a Code object
641 // containing the given address (which is supposedly faster than
642 // searching all code objects).
643 Code* FindDeoptimizingCode(Address addr);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100644
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000645 // Fill the given output frame's registers to contain the failure handler
646 // address and the number of parameters for a stub failure trampoline.
647 void SetPlatformCompiledStubRegisters(FrameDescription* output_frame,
648 CodeStubDescriptor* desc);
649
650 // Fill the given output frame's double registers with the original values
651 // from the input frame's double registers.
652 void CopyDoubleRegisters(FrameDescription* output_frame);
653
654 // Determines whether the input frame contains alignment padding by looking
655 // at the dynamic alignment state slot inside the frame.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100656 bool HasAlignmentPadding(SharedFunctionInfo* shared);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000657
Steve Block44f0eee2011-05-26 01:26:41 +0100658 Isolate* isolate_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100659 JSFunction* function_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000660 Code* compiled_code_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100661 unsigned bailout_id_;
662 BailoutType bailout_type_;
663 Address from_;
664 int fp_to_sp_delta_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000665 int has_alignment_padding_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100666 bool deoptimizing_throw_;
667 int catch_handler_data_;
668 int catch_handler_pc_offset_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100669
670 // Input frame description.
671 FrameDescription* input_;
672 // Number of output frames.
673 int output_count_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100674 // Number of output js frames.
675 int jsframe_count_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100676 // Array of output frame descriptions.
677 FrameDescription** output_;
678
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000679 // Key for lookup of previously materialized objects
680 Address stack_fp_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000681
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000682 TranslatedState translated_state_;
683 struct ValueToMaterialize {
684 Address output_slot_address_;
685 TranslatedFrame::iterator value_;
686 };
687 std::vector<ValueToMaterialize> values_to_materialize_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000688
689#ifdef DEBUG
690 DisallowHeapAllocation* disallow_heap_allocation_;
691#endif // DEBUG
692
693 CodeTracer::Scope* trace_scope_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100694
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000695 static const int table_entry_size_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100696
697 friend class FrameDescription;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000698 friend class DeoptimizedFrameInfo;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100699};
700
701
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000702class RegisterValues {
703 public:
704 intptr_t GetRegister(unsigned n) const {
705#if DEBUG
706 // This convoluted DCHECK is needed to work around a gcc problem that
707 // improperly detects an array bounds overflow in optimized debug builds
708 // when using a plain DCHECK.
709 if (n >= arraysize(registers_)) {
710 DCHECK(false);
711 return 0;
712 }
713#endif
714 return registers_[n];
715 }
716
717 double GetDoubleRegister(unsigned n) const {
718 DCHECK(n < arraysize(double_registers_));
719 return double_registers_[n];
720 }
721
722 void SetRegister(unsigned n, intptr_t value) {
723 DCHECK(n < arraysize(registers_));
724 registers_[n] = value;
725 }
726
727 void SetDoubleRegister(unsigned n, double value) {
728 DCHECK(n < arraysize(double_registers_));
729 double_registers_[n] = value;
730 }
731
732 intptr_t registers_[Register::kNumRegisters];
733 double double_registers_[DoubleRegister::kMaxNumRegisters];
734};
735
736
Ben Murdochb0fe1622011-05-05 13:52:32 +0100737class FrameDescription {
738 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100739 explicit FrameDescription(uint32_t frame_size, int parameter_count = 0);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100740
741 void* operator new(size_t size, uint32_t frame_size) {
Steve Block44f0eee2011-05-26 01:26:41 +0100742 // Subtracts kPointerSize, as the member frame_content_ already supplies
743 // the first element of the area to store the frame.
744 return malloc(size + frame_size - kPointerSize);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100745 }
746
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000747 void operator delete(void* pointer, uint32_t frame_size) {
748 free(pointer);
749 }
750
Ben Murdochb0fe1622011-05-05 13:52:32 +0100751 void operator delete(void* description) {
752 free(description);
753 }
754
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000755 uint32_t GetFrameSize() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000756 DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000757 return static_cast<uint32_t>(frame_size_);
758 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100759
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100760 unsigned GetOffsetFromSlotIndex(int slot_index);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100761
762 intptr_t GetFrameSlot(unsigned offset) {
763 return *GetFrameSlotPointer(offset);
764 }
765
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000766 Address GetFramePointerAddress() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100767 int fp_offset = GetFrameSize() - parameter_count() * kPointerSize -
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000768 StandardFrameConstants::kCallerSPOffset;
769 return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100770 }
771
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000772 RegisterValues* GetRegisterValues() { return &register_values_; }
773
Ben Murdochb0fe1622011-05-05 13:52:32 +0100774 void SetFrameSlot(unsigned offset, intptr_t value) {
775 *GetFrameSlotPointer(offset) = value;
776 }
777
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000778 void SetCallerPc(unsigned offset, intptr_t value);
779
780 void SetCallerFp(unsigned offset, intptr_t value);
781
782 void SetCallerConstantPool(unsigned offset, intptr_t value);
783
Ben Murdochb0fe1622011-05-05 13:52:32 +0100784 intptr_t GetRegister(unsigned n) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000785 return register_values_.GetRegister(n);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100786 }
787
788 double GetDoubleRegister(unsigned n) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000789 return register_values_.GetDoubleRegister(n);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100790 }
791
792 void SetRegister(unsigned n, intptr_t value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000793 register_values_.SetRegister(n, value);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100794 }
795
796 void SetDoubleRegister(unsigned n, double value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000797 register_values_.SetDoubleRegister(n, value);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100798 }
799
800 intptr_t GetTop() const { return top_; }
801 void SetTop(intptr_t top) { top_ = top; }
802
803 intptr_t GetPc() const { return pc_; }
804 void SetPc(intptr_t pc) { pc_ = pc; }
805
806 intptr_t GetFp() const { return fp_; }
807 void SetFp(intptr_t fp) { fp_ = fp; }
808
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100809 intptr_t GetContext() const { return context_; }
810 void SetContext(intptr_t context) { context_ = context; }
811
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000812 intptr_t GetConstantPool() const { return constant_pool_; }
813 void SetConstantPool(intptr_t constant_pool) {
814 constant_pool_ = constant_pool;
815 }
816
Ben Murdochb0fe1622011-05-05 13:52:32 +0100817 Smi* GetState() const { return state_; }
818 void SetState(Smi* state) { state_ = state; }
819
820 void SetContinuation(intptr_t pc) { continuation_ = pc; }
821
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100822 StackFrame::Type GetFrameType() const { return type_; }
823 void SetFrameType(StackFrame::Type type) { type_ = type; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000824
Ben Murdoch097c5b22016-05-18 11:27:45 +0100825 // Argument count, including receiver.
826 int parameter_count() { return parameter_count_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000827
Ben Murdochb0fe1622011-05-05 13:52:32 +0100828 static int registers_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000829 return OFFSET_OF(FrameDescription, register_values_.registers_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100830 }
831
832 static int double_registers_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000833 return OFFSET_OF(FrameDescription, register_values_.double_registers_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100834 }
835
836 static int frame_size_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000837 return offsetof(FrameDescription, frame_size_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100838 }
839
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000840 static int pc_offset() { return offsetof(FrameDescription, pc_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100841
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000842 static int state_offset() { return offsetof(FrameDescription, state_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100843
844 static int continuation_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000845 return offsetof(FrameDescription, continuation_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100846 }
847
848 static int frame_content_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000849 return offsetof(FrameDescription, frame_content_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100850 }
851
852 private:
853 static const uint32_t kZapUint32 = 0xbeeddead;
854
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000855 // Frame_size_ must hold a uint32_t value. It is only a uintptr_t to
856 // keep the variable-size array frame_content_ of type intptr_t at
857 // the end of the structure aligned.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100858 uintptr_t frame_size_; // Number of bytes.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100859 int parameter_count_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000860 RegisterValues register_values_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100861 intptr_t top_;
862 intptr_t pc_;
863 intptr_t fp_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100864 intptr_t context_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000865 intptr_t constant_pool_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100866 StackFrame::Type type_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100867 Smi* state_;
868
869 // Continuation is the PC where the execution continues after
870 // deoptimizing.
871 intptr_t continuation_;
872
Steve Block44f0eee2011-05-26 01:26:41 +0100873 // This must be at the end of the object as the object is allocated larger
874 // than it's definition indicate to extend this array.
875 intptr_t frame_content_[1];
876
Ben Murdochb0fe1622011-05-05 13:52:32 +0100877 intptr_t* GetFrameSlotPointer(unsigned offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000878 DCHECK(offset < frame_size_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100879 return reinterpret_cast<intptr_t*>(
880 reinterpret_cast<Address>(this) + frame_content_offset() + offset);
881 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100882
883 int ComputeFixedSize();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100884};
885
886
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000887class DeoptimizerData {
888 public:
889 explicit DeoptimizerData(MemoryAllocator* allocator);
890 ~DeoptimizerData();
891
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000892 private:
893 MemoryAllocator* allocator_;
894 int deopt_entry_code_entries_[Deoptimizer::kBailoutTypesWithCodeEntry];
895 MemoryChunk* deopt_entry_code_[Deoptimizer::kBailoutTypesWithCodeEntry];
896
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000897 Deoptimizer* current_;
898
899 friend class Deoptimizer;
900
901 DISALLOW_COPY_AND_ASSIGN(DeoptimizerData);
902};
903
904
Ben Murdochb0fe1622011-05-05 13:52:32 +0100905class TranslationBuffer BASE_EMBEDDED {
906 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000907 explicit TranslationBuffer(Zone* zone) : contents_(256, zone) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100908
909 int CurrentIndex() const { return contents_.length(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000910 void Add(int32_t value, Zone* zone);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100911
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000912 Handle<ByteArray> CreateByteArray(Factory* factory);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100913
914 private:
915 ZoneList<uint8_t> contents_;
916};
917
918
919class TranslationIterator BASE_EMBEDDED {
920 public:
921 TranslationIterator(ByteArray* buffer, int index)
922 : buffer_(buffer), index_(index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923 DCHECK(index >= 0 && index < buffer->length());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100924 }
925
926 int32_t Next();
927
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000928 bool HasNext() const { return index_ < buffer_->length(); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100929
930 void Skip(int n) {
931 for (int i = 0; i < n; i++) Next();
932 }
933
934 private:
935 ByteArray* buffer_;
936 int index_;
937};
938
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000939#define TRANSLATION_OPCODE_LIST(V) \
940 V(BEGIN) \
941 V(JS_FRAME) \
942 V(INTERPRETED_FRAME) \
943 V(CONSTRUCT_STUB_FRAME) \
944 V(GETTER_STUB_FRAME) \
945 V(SETTER_STUB_FRAME) \
946 V(ARGUMENTS_ADAPTOR_FRAME) \
947 V(COMPILED_STUB_FRAME) \
948 V(DUPLICATED_OBJECT) \
949 V(ARGUMENTS_OBJECT) \
950 V(CAPTURED_OBJECT) \
951 V(REGISTER) \
952 V(INT32_REGISTER) \
953 V(UINT32_REGISTER) \
954 V(BOOL_REGISTER) \
955 V(DOUBLE_REGISTER) \
956 V(STACK_SLOT) \
957 V(INT32_STACK_SLOT) \
958 V(UINT32_STACK_SLOT) \
959 V(BOOL_STACK_SLOT) \
960 V(DOUBLE_STACK_SLOT) \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100961 V(LITERAL)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000962
Ben Murdochb0fe1622011-05-05 13:52:32 +0100963class Translation BASE_EMBEDDED {
964 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000965#define DECLARE_TRANSLATION_OPCODE_ENUM(item) item,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100966 enum Opcode {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000967 TRANSLATION_OPCODE_LIST(DECLARE_TRANSLATION_OPCODE_ENUM)
968 LAST = LITERAL
Ben Murdochb0fe1622011-05-05 13:52:32 +0100969 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000970#undef DECLARE_TRANSLATION_OPCODE_ENUM
Ben Murdochb0fe1622011-05-05 13:52:32 +0100971
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000972 Translation(TranslationBuffer* buffer, int frame_count, int jsframe_count,
973 Zone* zone)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100974 : buffer_(buffer),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000975 index_(buffer->CurrentIndex()),
976 zone_(zone) {
977 buffer_->Add(BEGIN, zone);
978 buffer_->Add(frame_count, zone);
979 buffer_->Add(jsframe_count, zone);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100980 }
981
982 int index() const { return index_; }
983
984 // Commands.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000985 void BeginJSFrame(BailoutId node_id, int literal_id, unsigned height);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000986 void BeginInterpretedFrame(BailoutId bytecode_offset, int literal_id,
987 unsigned height);
988 void BeginCompiledStubFrame(int height);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100989 void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
990 void BeginConstructStubFrame(int literal_id, unsigned height);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000991 void BeginGetterStubFrame(int literal_id);
992 void BeginSetterStubFrame(int literal_id);
993 void BeginArgumentsObject(int args_length);
994 void BeginCapturedObject(int length);
995 void DuplicateObject(int object_index);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100996 void StoreRegister(Register reg);
997 void StoreInt32Register(Register reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998 void StoreUint32Register(Register reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000999 void StoreBoolRegister(Register reg);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001000 void StoreDoubleRegister(DoubleRegister reg);
1001 void StoreStackSlot(int index);
1002 void StoreInt32StackSlot(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001003 void StoreUint32StackSlot(int index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001004 void StoreBoolStackSlot(int index);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001005 void StoreDoubleStackSlot(int index);
1006 void StoreLiteral(int literal_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001007 void StoreArgumentsObject(bool args_known, int args_index, int args_length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001008 void StoreJSFrameFunction();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001009
1010 Zone* zone() const { return zone_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001011
1012 static int NumberOfOperandsFor(Opcode opcode);
1013
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001014#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001015 static const char* StringFor(Opcode opcode);
1016#endif
1017
1018 private:
1019 TranslationBuffer* buffer_;
1020 int index_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001021 Zone* zone_;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001022};
1023
1024
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001025class MaterializedObjectStore {
1026 public:
1027 explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) {
1028 }
1029
1030 Handle<FixedArray> Get(Address fp);
1031 void Set(Address fp, Handle<FixedArray> materialized_objects);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001032 bool Remove(Address fp);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001033
1034 private:
1035 Isolate* isolate() { return isolate_; }
1036 Handle<FixedArray> GetStackEntries();
1037 Handle<FixedArray> EnsureStackEntries(int size);
1038
1039 int StackIdToIndex(Address fp);
1040
1041 Isolate* isolate_;
1042 List<Address> frame_fps_;
Ben Murdoch8b112d22011-06-08 16:22:53 +01001043};
1044
1045
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001046// Class used to represent an unoptimized frame when the debugger
1047// needs to inspect a frame that is part of an optimized frame. The
1048// internally used FrameDescription objects are not GC safe so for use
1049// by the debugger frame information is copied to an object of this type.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001050// Represents parameters in unadapted form so their number might mismatch
1051// formal parameter count.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001052class DeoptimizedFrameInfo : public Malloced {
1053 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001054 DeoptimizedFrameInfo(TranslatedState* state,
1055 TranslatedState::iterator frame_it, Isolate* isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001056
1057 // Return the number of incoming arguments.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001058 int parameters_count() { return static_cast<int>(parameters_.size()); }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001059
1060 // Return the height of the expression stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001061 int expression_count() { return static_cast<int>(expression_stack_.size()); }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001062
1063 // Get the frame function.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001064 Handle<JSFunction> GetFunction() { return function_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001065
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001066 // Get the frame context.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001067 Handle<Object> GetContext() { return context_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001068
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001069 // Check if this frame is preceded by construct stub frame. The bottom-most
1070 // inlined frame might still be called by an uninlined construct stub.
1071 bool HasConstructStub() {
1072 return has_construct_stub_;
1073 }
1074
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001075 // Get an incoming argument.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001076 Handle<Object> GetParameter(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001077 DCHECK(0 <= index && index < parameters_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001078 return parameters_[index];
1079 }
1080
1081 // Get an expression from the expression stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001082 Handle<Object> GetExpression(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001083 DCHECK(0 <= index && index < expression_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001084 return expression_stack_[index];
1085 }
1086
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001087 int GetSourcePosition() {
1088 return source_position_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001089 }
1090
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001091 private:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001092 // Set an incoming argument.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001093 void SetParameter(int index, Handle<Object> obj) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001094 DCHECK(0 <= index && index < parameters_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001095 parameters_[index] = obj;
1096 }
1097
1098 // Set an expression on the expression stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001099 void SetExpression(int index, Handle<Object> obj) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001100 DCHECK(0 <= index && index < expression_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001101 expression_stack_[index] = obj;
1102 }
1103
Ben Murdoch097c5b22016-05-18 11:27:45 +01001104 Handle<JSFunction> function_;
1105 Handle<Object> context_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001106 bool has_construct_stub_;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001107 std::vector<Handle<Object> > parameters_;
1108 std::vector<Handle<Object> > expression_stack_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001109 int source_position_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001110
1111 friend class Deoptimizer;
1112};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001113
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001114} // namespace internal
1115} // namespace v8
Ben Murdochb0fe1622011-05-05 13:52:32 +01001116
1117#endif // V8_DEOPTIMIZER_H_