blob: 21ca84ed5271134c020e8b2c02aad19cab6c4890 [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,
Ben Murdochda12d292016-06-02 14:46:10 +0100119 kTailCallerFunction,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000120 kArgumentsAdaptor,
121 kConstructStub,
122 kCompiledStub,
123 kInvalid
124 };
Ben Murdoch8b112d22011-06-08 16:22:53 +0100125
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 int GetValueCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128 Kind kind() const { return kind_; }
129 BailoutId node_id() const { return node_id_; }
130 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
131 int height() const { return height_; }
132
Ben Murdoch097c5b22016-05-18 11:27:45 +0100133 SharedFunctionInfo* raw_shared_info() const {
134 CHECK_NOT_NULL(raw_shared_info_);
135 return raw_shared_info_;
136 }
137
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138 class iterator {
139 public:
140 iterator& operator++() {
141 AdvanceIterator(&position_);
142 return *this;
143 }
144
145 iterator operator++(int) {
146 iterator original(position_);
147 AdvanceIterator(&position_);
148 return original;
149 }
150
151 bool operator==(const iterator& other) const {
152 return position_ == other.position_;
153 }
154 bool operator!=(const iterator& other) const { return !(*this == other); }
155
156 TranslatedValue& operator*() { return (*position_); }
157 TranslatedValue* operator->() { return &(*position_); }
158
159 private:
160 friend TranslatedFrame;
161
162 explicit iterator(std::deque<TranslatedValue>::iterator position)
163 : position_(position) {}
164
165 std::deque<TranslatedValue>::iterator position_;
166 };
167
168 typedef TranslatedValue& reference;
169 typedef TranslatedValue const& const_reference;
170
171 iterator begin() { return iterator(values_.begin()); }
172 iterator end() { return iterator(values_.end()); }
173
174 reference front() { return values_.front(); }
175 const_reference front() const { return values_.front(); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100176
177 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000178 friend class TranslatedState;
179
180 // Constructor static methods.
181 static TranslatedFrame JSFrame(BailoutId node_id,
182 SharedFunctionInfo* shared_info, int height);
183 static TranslatedFrame InterpretedFrame(BailoutId bytecode_offset,
184 SharedFunctionInfo* shared_info,
185 int height);
186 static TranslatedFrame AccessorFrame(Kind kind,
187 SharedFunctionInfo* shared_info);
188 static TranslatedFrame ArgumentsAdaptorFrame(SharedFunctionInfo* shared_info,
189 int height);
Ben Murdochda12d292016-06-02 14:46:10 +0100190 static TranslatedFrame TailCallerFrame(SharedFunctionInfo* shared_info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191 static TranslatedFrame ConstructStubFrame(SharedFunctionInfo* shared_info,
192 int height);
193 static TranslatedFrame CompiledStubFrame(int height, Isolate* isolate) {
194 return TranslatedFrame(kCompiledStub, isolate, nullptr, height);
195 }
196 static TranslatedFrame InvalidFrame() {
197 return TranslatedFrame(kInvalid, nullptr);
198 }
199
200 static void AdvanceIterator(std::deque<TranslatedValue>::iterator* iter);
201
202 TranslatedFrame(Kind kind, Isolate* isolate,
203 SharedFunctionInfo* shared_info = nullptr, int height = 0)
204 : kind_(kind),
205 node_id_(BailoutId::None()),
206 raw_shared_info_(shared_info),
207 height_(height),
208 isolate_(isolate) {}
209
210
211 void Add(const TranslatedValue& value) { values_.push_back(value); }
212 void Handlify();
213
214 Kind kind_;
215 BailoutId node_id_;
216 SharedFunctionInfo* raw_shared_info_;
217 Handle<SharedFunctionInfo> shared_info_;
218 int height_;
219 Isolate* isolate_;
220
221 typedef std::deque<TranslatedValue> ValuesContainer;
222
223 ValuesContainer values_;
224};
225
226
227// Auxiliary class for translating deoptimization values.
228// Typical usage sequence:
229//
230// 1. Construct the instance. This will involve reading out the translations
231// and resolving them to values using the supplied frame pointer and
232// machine state (registers). This phase is guaranteed not to allocate
233// and not to use any HandleScope. Any object pointers will be stored raw.
234//
235// 2. Handlify pointers. This will convert all the raw pointers to handles.
236//
237// 3. Reading out the frame values.
238//
239// Note: After the instance is constructed, it is possible to iterate over
240// the values eagerly.
241
242class TranslatedState {
243 public:
244 TranslatedState();
245 explicit TranslatedState(JavaScriptFrame* frame);
246
247 void Prepare(bool has_adapted_arguments, Address stack_frame_pointer);
248
249 // Store newly materialized values into the isolate.
250 void StoreMaterializedValuesAndDeopt();
251
252 typedef std::vector<TranslatedFrame>::iterator iterator;
253 iterator begin() { return frames_.begin(); }
254 iterator end() { return frames_.end(); }
255
256 typedef std::vector<TranslatedFrame>::const_iterator const_iterator;
257 const_iterator begin() const { return frames_.begin(); }
258 const_iterator end() const { return frames_.end(); }
259
260 std::vector<TranslatedFrame>& frames() { return frames_; }
261
262 TranslatedFrame* GetArgumentsInfoFromJSFrameIndex(int jsframe_index,
263 int* arguments_count);
264
265 Isolate* isolate() { return isolate_; }
266
267 void Init(Address input_frame_pointer, TranslationIterator* iterator,
268 FixedArray* literal_array, RegisterValues* registers,
269 FILE* trace_file);
270
271 private:
272 friend TranslatedValue;
273
274 TranslatedFrame CreateNextTranslatedFrame(TranslationIterator* iterator,
275 FixedArray* literal_array,
276 Address fp,
277 FILE* trace_file);
278 TranslatedValue CreateNextTranslatedValue(int frame_index, int value_index,
279 TranslationIterator* iterator,
280 FixedArray* literal_array,
281 Address fp,
282 RegisterValues* registers,
283 FILE* trace_file);
284
285 void UpdateFromPreviouslyMaterializedObjects();
286 Handle<Object> MaterializeAt(int frame_index, int* value_index);
287 Handle<Object> MaterializeObjectAt(int object_index);
288 bool GetAdaptedArguments(Handle<JSObject>* result, int frame_index);
289
290 static uint32_t GetUInt32Slot(Address fp, int slot_index);
291
292 std::vector<TranslatedFrame> frames_;
293 Isolate* isolate_;
294 Address stack_frame_pointer_;
295 bool has_adapted_arguments_;
296
297 struct ObjectPosition {
298 int frame_index_;
299 int value_index_;
300 };
301 std::deque<ObjectPosition> object_positions_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100302};
303
304
305class OptimizedFunctionVisitor BASE_EMBEDDED {
306 public:
307 virtual ~OptimizedFunctionVisitor() {}
308
309 // Function which is called before iteration of any optimized functions
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310 // from given native context.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100311 virtual void EnterContext(Context* context) = 0;
312
313 virtual void VisitFunction(JSFunction* function) = 0;
314
315 // Function which is called after iteration of all optimized functions
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000316 // from given native context.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100317 virtual void LeaveContext(Context* context) = 0;
318};
319
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320#define DEOPT_MESSAGES_LIST(V) \
321 V(kAccessCheck, "Access check needed") \
322 V(kNoReason, "no reason") \
323 V(kConstantGlobalVariableAssignment, "Constant global variable assignment") \
324 V(kConversionOverflow, "conversion overflow") \
325 V(kDivisionByZero, "division by zero") \
326 V(kElementsKindUnhandledInKeyedLoadGenericStub, \
327 "ElementsKind unhandled in KeyedLoadGenericStub") \
328 V(kExpectedHeapNumber, "Expected heap number") \
329 V(kExpectedSmi, "Expected smi") \
330 V(kForcedDeoptToRuntime, "Forced deopt to runtime") \
331 V(kHole, "hole") \
332 V(kHoleyArrayDespitePackedElements_kindFeedback, \
333 "Holey array despite packed elements_kind feedback") \
334 V(kInstanceMigrationFailed, "instance migration failed") \
335 V(kInsufficientTypeFeedbackForCallWithArguments, \
336 "Insufficient type feedback for call with arguments") \
Ben Murdochda12d292016-06-02 14:46:10 +0100337 V(kFastArrayPushFailed, "Falling off the fast path for FastArrayPush") \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000338 V(kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation, \
339 "Insufficient type feedback for combined type of binary operation") \
340 V(kInsufficientTypeFeedbackForGenericNamedAccess, \
341 "Insufficient type feedback for generic named access") \
342 V(kInsufficientTypeFeedbackForKeyedLoad, \
343 "Insufficient type feedback for keyed load") \
344 V(kInsufficientTypeFeedbackForKeyedStore, \
345 "Insufficient type feedback for keyed store") \
346 V(kInsufficientTypeFeedbackForLHSOfBinaryOperation, \
347 "Insufficient type feedback for LHS of binary operation") \
348 V(kInsufficientTypeFeedbackForRHSOfBinaryOperation, \
349 "Insufficient type feedback for RHS of binary operation") \
350 V(kKeyIsNegative, "key is negative") \
351 V(kLiteralsWereDisposed, "literals have been disposed") \
352 V(kLostPrecision, "lost precision") \
353 V(kLostPrecisionOrNaN, "lost precision or NaN") \
354 V(kMementoFound, "memento found") \
355 V(kMinusZero, "minus zero") \
356 V(kNaN, "NaN") \
357 V(kNegativeKeyEncountered, "Negative key encountered") \
358 V(kNegativeValue, "negative value") \
359 V(kNoCache, "no cache") \
360 V(kNonStrictElementsInKeyedLoadGenericStub, \
361 "non-strict elements in KeyedLoadGenericStub") \
362 V(kNotADateObject, "not a date object") \
363 V(kNotAHeapNumber, "not a heap number") \
364 V(kNotAHeapNumberUndefinedBoolean, "not a heap number/undefined/true/false") \
365 V(kNotAHeapNumberUndefined, "not a heap number/undefined") \
366 V(kNotAJavaScriptObject, "not a JavaScript object") \
367 V(kNotASmi, "not a Smi") \
368 V(kNull, "null") \
369 V(kOutOfBounds, "out of bounds") \
370 V(kOutsideOfRange, "Outside of range") \
371 V(kOverflow, "overflow") \
372 V(kProxy, "proxy") \
373 V(kReceiverWasAGlobalObject, "receiver was a global object") \
374 V(kSmi, "Smi") \
375 V(kTooManyArguments, "too many arguments") \
376 V(kTooManyUndetectableTypes, "Too many undetectable types") \
377 V(kTracingElementsTransitions, "Tracing elements transitions") \
378 V(kTypeMismatchBetweenFeedbackAndConstant, \
379 "Type mismatch between feedback and constant") \
380 V(kUndefined, "undefined") \
381 V(kUnexpectedCellContentsInConstantGlobalStore, \
382 "Unexpected cell contents in constant global store") \
383 V(kUnexpectedCellContentsInGlobalStore, \
384 "Unexpected cell contents in global store") \
385 V(kUnexpectedObject, "unexpected object") \
386 V(kUnexpectedRHSOfBinaryOperation, "Unexpected RHS of binary operation") \
387 V(kUninitializedBoilerplateInFastClone, \
388 "Uninitialized boilerplate in fast clone") \
389 V(kUninitializedBoilerplateLiterals, "Uninitialized boilerplate literals") \
390 V(kUnknownMapInPolymorphicAccess, "Unknown map in polymorphic access") \
391 V(kUnknownMapInPolymorphicCall, "Unknown map in polymorphic call") \
392 V(kUnknownMapInPolymorphicElementAccess, \
393 "Unknown map in polymorphic element access") \
394 V(kUnknownMap, "Unknown map") \
395 V(kValueMismatch, "value mismatch") \
396 V(kWrongInstanceType, "wrong instance type") \
397 V(kWrongMap, "wrong map") \
398 V(kUndefinedOrNullInForIn, "null or undefined in for-in") \
399 V(kUndefinedOrNullInToObject, "null or undefined in ToObject")
400
Ben Murdochb0fe1622011-05-05 13:52:32 +0100401class Deoptimizer : public Malloced {
402 public:
Ben Murdochda12d292016-06-02 14:46:10 +0100403 enum BailoutType { EAGER, LAZY, SOFT, kLastBailoutType = SOFT };
Ben Murdochb0fe1622011-05-05 13:52:32 +0100404
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000405#define DEOPT_MESSAGES_CONSTANTS(C, T) C,
406 enum DeoptReason {
407 DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_CONSTANTS) kLastDeoptReason
408 };
409#undef DEOPT_MESSAGES_CONSTANTS
410 static const char* GetDeoptReason(DeoptReason deopt_reason);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000411
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 struct DeoptInfo {
413 DeoptInfo(SourcePosition position, const char* m, DeoptReason d)
414 : position(position), mnemonic(m), deopt_reason(d), inlining_id(0) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000415
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 SourcePosition position;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000417 const char* mnemonic;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000418 DeoptReason deopt_reason;
419 int inlining_id;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000420 };
421
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000422 static DeoptInfo GetDeoptInfo(Code* code, byte* from);
423
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000424 struct JumpTableEntry : public ZoneObject {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000425 inline JumpTableEntry(Address entry, const DeoptInfo& deopt_info,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000426 Deoptimizer::BailoutType type, bool frame)
427 : label(),
428 address(entry),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000429 deopt_info(deopt_info),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000430 bailout_type(type),
431 needs_frame(frame) {}
432
433 bool IsEquivalentTo(const JumpTableEntry& other) const {
434 return address == other.address && bailout_type == other.bailout_type &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000435 needs_frame == other.needs_frame;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000436 }
437
438 Label label;
439 Address address;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000440 DeoptInfo deopt_info;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000441 Deoptimizer::BailoutType bailout_type;
442 bool needs_frame;
443 };
444
445 static bool TraceEnabledFor(BailoutType deopt_type,
446 StackFrame::Type frame_type);
447 static const char* MessageFor(BailoutType type);
448
Ben Murdochb0fe1622011-05-05 13:52:32 +0100449 int output_count() const { return output_count_; }
450
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451 Handle<JSFunction> function() const { return Handle<JSFunction>(function_); }
452 Handle<Code> compiled_code() const { return Handle<Code>(compiled_code_); }
453 BailoutType bailout_type() const { return bailout_type_; }
454
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100455 // Number of created JS frames. Not all created frames are necessarily JS.
456 int jsframe_count() const { return jsframe_count_; }
457
Ben Murdochb0fe1622011-05-05 13:52:32 +0100458 static Deoptimizer* New(JSFunction* function,
459 BailoutType type,
460 unsigned bailout_id,
461 Address from,
Steve Block44f0eee2011-05-26 01:26:41 +0100462 int fp_to_sp_delta,
463 Isolate* isolate);
464 static Deoptimizer* Grab(Isolate* isolate);
465
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000466 // The returned object with information on the optimized frame needs to be
467 // freed before another one can be generated.
468 static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100469 int jsframe_index,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000470 Isolate* isolate);
471 static void DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
472 Isolate* isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000473
Steve Block44f0eee2011-05-26 01:26:41 +0100474 // Makes sure that there is enough room in the relocation
475 // information of a code object to perform lazy deoptimization
476 // patching. If there is not enough room a new relocation
477 // information object is allocated and comments are added until it
478 // is big enough.
479 static void EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100480
481 // Deoptimize the function now. Its current optimized code will never be run
482 // again and any activations of the optimized code will get deoptimized when
483 // execution returns.
484 static void DeoptimizeFunction(JSFunction* function);
485
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000486 // Deoptimize all code in the given isolate.
487 static void DeoptimizeAll(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100488
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000489 // Deoptimizes all optimized code that has been previously marked
490 // (via code->set_marked_for_deoptimization) and unlinks all functions that
491 // refer to that code.
492 static void DeoptimizeMarkedCode(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100493
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494 // Visit all the known optimized functions in a given isolate.
495 static void VisitAllOptimizedFunctions(
496 Isolate* isolate, OptimizedFunctionVisitor* visitor);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100497
Steve Block1e0659c2011-05-24 12:43:12 +0100498 // The size in bytes of the code required at a lazy deopt patch site.
499 static int patch_size();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100500
Ben Murdochb0fe1622011-05-05 13:52:32 +0100501 ~Deoptimizer();
502
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503 void MaterializeHeapObjects(JavaScriptFrameIterator* it);
504
Ben Murdoch8b112d22011-06-08 16:22:53 +0100505 static void ComputeOutputFrames(Deoptimizer* deoptimizer);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100506
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000507
508 enum GetEntryMode {
509 CALCULATE_ENTRY_ADDRESS,
510 ENSURE_ENTRY_CODE
511 };
512
513
514 static Address GetDeoptimizationEntry(
515 Isolate* isolate,
516 int id,
517 BailoutType type,
518 GetEntryMode mode = ENSURE_ENTRY_CODE);
519 static int GetDeoptimizationId(Isolate* isolate,
520 Address addr,
521 BailoutType type);
Steve Block9fac8402011-05-12 15:51:54 +0100522 static int GetOutputInfo(DeoptimizationOutputData* data,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523 BailoutId node_id,
Steve Block9fac8402011-05-12 15:51:54 +0100524 SharedFunctionInfo* shared);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100525
Ben Murdochb0fe1622011-05-05 13:52:32 +0100526 // Code generation support.
527 static int input_offset() { return OFFSET_OF(Deoptimizer, input_); }
528 static int output_count_offset() {
529 return OFFSET_OF(Deoptimizer, output_count_);
530 }
531 static int output_offset() { return OFFSET_OF(Deoptimizer, output_); }
532
Ben Murdochda12d292016-06-02 14:46:10 +0100533 static int caller_frame_top_offset() {
534 return OFFSET_OF(Deoptimizer, caller_frame_top_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535 }
536
Steve Block44f0eee2011-05-26 01:26:41 +0100537 static int GetDeoptimizedCodeCount(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100538
539 static const int kNotDeoptimizationEntry = -1;
540
541 // Generators for the deoptimization entry code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000542 class TableEntryGenerator BASE_EMBEDDED {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100543 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000544 TableEntryGenerator(MacroAssembler* masm, BailoutType type, int count)
545 : masm_(masm), type_(type), count_(count) {}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100546
547 void Generate();
548
549 protected:
550 MacroAssembler* masm() const { return masm_; }
551 BailoutType type() const { return type_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552 Isolate* isolate() const { return masm_->isolate(); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100553
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000554 void GeneratePrologue();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100555
556 private:
557 int count() const { return count_; }
558
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000559 MacroAssembler* masm_;
560 Deoptimizer::BailoutType type_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100561 int count_;
562 };
563
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100564 int ConvertJSFrameIndexToFrameIndex(int jsframe_index);
565
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000566 static size_t GetMaxDeoptTableSize();
567
568 static void EnsureCodeForDeoptimizationEntry(Isolate* isolate,
569 BailoutType type,
570 int max_entry_id);
571
572 Isolate* isolate() const { return isolate_; }
573
Ben Murdochb0fe1622011-05-05 13:52:32 +0100574 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000575 static const int kMinNumberOfEntries = 64;
576 static const int kMaxNumberOfEntries = 16384;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100577
Steve Block44f0eee2011-05-26 01:26:41 +0100578 Deoptimizer(Isolate* isolate,
579 JSFunction* function,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100580 BailoutType type,
581 unsigned bailout_id,
582 Address from,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000583 int fp_to_sp_delta,
584 Code* optimized_code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000585 Code* FindOptimizedCode(JSFunction* function, Code* optimized_code);
586 void PrintFunctionName();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100587 void DeleteFrameDescriptions();
588
589 void DoComputeOutputFrames();
Ben Murdochda12d292016-06-02 14:46:10 +0100590 void DoComputeJSFrame(TranslatedFrame* translated_frame, int frame_index,
591 bool goto_catch_handler);
592 void DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
593 int frame_index, bool goto_catch_handler);
594 void DoComputeArgumentsAdaptorFrame(TranslatedFrame* translated_frame,
595 int frame_index);
596 void DoComputeTailCallerFrame(TranslatedFrame* translated_frame,
597 int frame_index);
598 void DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
599 int frame_index);
600 void DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
601 int frame_index, bool is_setter_stub_frame);
602 void DoComputeCompiledStubFrame(TranslatedFrame* translated_frame,
603 int frame_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000604
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000605 void WriteTranslatedValueToOutput(
606 TranslatedFrame::iterator* iterator, int* input_index, int frame_index,
607 unsigned output_offset, const char* debug_hint_string = nullptr,
608 Address output_address_for_materialization = nullptr);
609 void WriteValueToOutput(Object* value, int input_index, int frame_index,
610 unsigned output_offset,
611 const char* debug_hint_string);
612 void DebugPrintOutputSlot(intptr_t value, int frame_index,
613 unsigned output_offset,
614 const char* debug_hint_string);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100615
Ben Murdochda12d292016-06-02 14:46:10 +0100616 unsigned ComputeInputFrameAboveFpFixedSize() const;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100617 unsigned ComputeInputFrameSize() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100618 static unsigned ComputeJavascriptFixedSize(SharedFunctionInfo* shared);
619 static unsigned ComputeInterpretedFixedSize(SharedFunctionInfo* shared);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100620
Ben Murdoch097c5b22016-05-18 11:27:45 +0100621 static unsigned ComputeIncomingArgumentSize(SharedFunctionInfo* shared);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000622 static unsigned ComputeOutgoingArgumentSize(Code* code, unsigned bailout_id);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100623
624 Object* ComputeLiteral(int index) const;
625
Ben Murdochb0fe1622011-05-05 13:52:32 +0100626 static void GenerateDeoptimizationEntries(
627 MacroAssembler* masm, int count, BailoutType type);
628
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 // Marks all the code in the given context for deoptimization.
630 static void MarkAllCodeForContext(Context* native_context);
631
632 // Visit all the known optimized functions in a given context.
633 static void VisitAllOptimizedFunctionsForContext(
634 Context* context, OptimizedFunctionVisitor* visitor);
635
636 // Deoptimizes all code marked in the given context.
637 static void DeoptimizeMarkedCodeForContext(Context* native_context);
638
639 // Patch the given code so that it will deoptimize itself.
640 static void PatchCodeForDeoptimization(Isolate* isolate, Code* code);
641
642 // Searches the list of known deoptimizing code for a Code object
643 // containing the given address (which is supposedly faster than
644 // searching all code objects).
645 Code* FindDeoptimizingCode(Address addr);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100646
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000647 // Fill the given output frame's registers to contain the failure handler
648 // address and the number of parameters for a stub failure trampoline.
649 void SetPlatformCompiledStubRegisters(FrameDescription* output_frame,
650 CodeStubDescriptor* desc);
651
652 // Fill the given output frame's double registers with the original values
653 // from the input frame's double registers.
654 void CopyDoubleRegisters(FrameDescription* output_frame);
655
Steve Block44f0eee2011-05-26 01:26:41 +0100656 Isolate* isolate_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100657 JSFunction* function_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000658 Code* compiled_code_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100659 unsigned bailout_id_;
660 BailoutType bailout_type_;
661 Address from_;
662 int fp_to_sp_delta_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100663 bool deoptimizing_throw_;
664 int catch_handler_data_;
665 int catch_handler_pc_offset_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100666
667 // Input frame description.
668 FrameDescription* input_;
669 // Number of output frames.
670 int output_count_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100671 // Number of output js frames.
672 int jsframe_count_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100673 // Array of output frame descriptions.
674 FrameDescription** output_;
675
Ben Murdochda12d292016-06-02 14:46:10 +0100676 // Caller frame details computed from input frame.
677 intptr_t caller_frame_top_;
678 intptr_t caller_fp_;
679 intptr_t caller_pc_;
680 intptr_t caller_constant_pool_;
681 intptr_t input_frame_context_;
682
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000683 // Key for lookup of previously materialized objects
Ben Murdochda12d292016-06-02 14:46:10 +0100684 intptr_t stack_fp_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000685
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000686 TranslatedState translated_state_;
687 struct ValueToMaterialize {
688 Address output_slot_address_;
689 TranslatedFrame::iterator value_;
690 };
691 std::vector<ValueToMaterialize> values_to_materialize_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000692
693#ifdef DEBUG
694 DisallowHeapAllocation* disallow_heap_allocation_;
695#endif // DEBUG
696
697 CodeTracer::Scope* trace_scope_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100698
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000699 static const int table_entry_size_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100700
701 friend class FrameDescription;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000702 friend class DeoptimizedFrameInfo;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100703};
704
705
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706class RegisterValues {
707 public:
708 intptr_t GetRegister(unsigned n) const {
709#if DEBUG
710 // This convoluted DCHECK is needed to work around a gcc problem that
711 // improperly detects an array bounds overflow in optimized debug builds
712 // when using a plain DCHECK.
713 if (n >= arraysize(registers_)) {
714 DCHECK(false);
715 return 0;
716 }
717#endif
718 return registers_[n];
719 }
720
721 double GetDoubleRegister(unsigned n) const {
722 DCHECK(n < arraysize(double_registers_));
723 return double_registers_[n];
724 }
725
726 void SetRegister(unsigned n, intptr_t value) {
727 DCHECK(n < arraysize(registers_));
728 registers_[n] = value;
729 }
730
731 void SetDoubleRegister(unsigned n, double value) {
732 DCHECK(n < arraysize(double_registers_));
733 double_registers_[n] = value;
734 }
735
736 intptr_t registers_[Register::kNumRegisters];
737 double double_registers_[DoubleRegister::kMaxNumRegisters];
738};
739
740
Ben Murdochb0fe1622011-05-05 13:52:32 +0100741class FrameDescription {
742 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100743 explicit FrameDescription(uint32_t frame_size, int parameter_count = 0);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100744
745 void* operator new(size_t size, uint32_t frame_size) {
Steve Block44f0eee2011-05-26 01:26:41 +0100746 // Subtracts kPointerSize, as the member frame_content_ already supplies
747 // the first element of the area to store the frame.
748 return malloc(size + frame_size - kPointerSize);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100749 }
750
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000751 void operator delete(void* pointer, uint32_t frame_size) {
752 free(pointer);
753 }
754
Ben Murdochb0fe1622011-05-05 13:52:32 +0100755 void operator delete(void* description) {
756 free(description);
757 }
758
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000759 uint32_t GetFrameSize() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000760 DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000761 return static_cast<uint32_t>(frame_size_);
762 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100763
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100764 unsigned GetOffsetFromSlotIndex(int slot_index);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100765
766 intptr_t GetFrameSlot(unsigned offset) {
767 return *GetFrameSlotPointer(offset);
768 }
769
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000770 Address GetFramePointerAddress() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100771 int fp_offset = GetFrameSize() - parameter_count() * kPointerSize -
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000772 StandardFrameConstants::kCallerSPOffset;
773 return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100774 }
775
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000776 RegisterValues* GetRegisterValues() { return &register_values_; }
777
Ben Murdochb0fe1622011-05-05 13:52:32 +0100778 void SetFrameSlot(unsigned offset, intptr_t value) {
779 *GetFrameSlotPointer(offset) = value;
780 }
781
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000782 void SetCallerPc(unsigned offset, intptr_t value);
783
784 void SetCallerFp(unsigned offset, intptr_t value);
785
786 void SetCallerConstantPool(unsigned offset, intptr_t value);
787
Ben Murdochb0fe1622011-05-05 13:52:32 +0100788 intptr_t GetRegister(unsigned n) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000789 return register_values_.GetRegister(n);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100790 }
791
792 double GetDoubleRegister(unsigned n) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000793 return register_values_.GetDoubleRegister(n);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100794 }
795
796 void SetRegister(unsigned n, intptr_t value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000797 register_values_.SetRegister(n, value);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100798 }
799
800 void SetDoubleRegister(unsigned n, double value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000801 register_values_.SetDoubleRegister(n, value);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100802 }
803
804 intptr_t GetTop() const { return top_; }
805 void SetTop(intptr_t top) { top_ = top; }
806
807 intptr_t GetPc() const { return pc_; }
808 void SetPc(intptr_t pc) { pc_ = pc; }
809
810 intptr_t GetFp() const { return fp_; }
811 void SetFp(intptr_t fp) { fp_ = fp; }
812
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100813 intptr_t GetContext() const { return context_; }
814 void SetContext(intptr_t context) { context_ = context; }
815
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000816 intptr_t GetConstantPool() const { return constant_pool_; }
817 void SetConstantPool(intptr_t constant_pool) {
818 constant_pool_ = constant_pool;
819 }
820
Ben Murdochb0fe1622011-05-05 13:52:32 +0100821 Smi* GetState() const { return state_; }
822 void SetState(Smi* state) { state_ = state; }
823
824 void SetContinuation(intptr_t pc) { continuation_ = pc; }
825
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100826 StackFrame::Type GetFrameType() const { return type_; }
827 void SetFrameType(StackFrame::Type type) { type_ = type; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000828
Ben Murdoch097c5b22016-05-18 11:27:45 +0100829 // Argument count, including receiver.
830 int parameter_count() { return parameter_count_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000831
Ben Murdochb0fe1622011-05-05 13:52:32 +0100832 static int registers_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000833 return OFFSET_OF(FrameDescription, register_values_.registers_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100834 }
835
836 static int double_registers_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000837 return OFFSET_OF(FrameDescription, register_values_.double_registers_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100838 }
839
840 static int frame_size_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000841 return offsetof(FrameDescription, frame_size_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100842 }
843
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000844 static int pc_offset() { return offsetof(FrameDescription, pc_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100845
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000846 static int state_offset() { return offsetof(FrameDescription, state_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100847
848 static int continuation_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000849 return offsetof(FrameDescription, continuation_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100850 }
851
852 static int frame_content_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853 return offsetof(FrameDescription, frame_content_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100854 }
855
856 private:
857 static const uint32_t kZapUint32 = 0xbeeddead;
858
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000859 // Frame_size_ must hold a uint32_t value. It is only a uintptr_t to
860 // keep the variable-size array frame_content_ of type intptr_t at
861 // the end of the structure aligned.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100862 uintptr_t frame_size_; // Number of bytes.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100863 int parameter_count_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000864 RegisterValues register_values_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100865 intptr_t top_;
866 intptr_t pc_;
867 intptr_t fp_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100868 intptr_t context_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000869 intptr_t constant_pool_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100870 StackFrame::Type type_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100871 Smi* state_;
872
873 // Continuation is the PC where the execution continues after
874 // deoptimizing.
875 intptr_t continuation_;
876
Steve Block44f0eee2011-05-26 01:26:41 +0100877 // This must be at the end of the object as the object is allocated larger
878 // than it's definition indicate to extend this array.
879 intptr_t frame_content_[1];
880
Ben Murdochb0fe1622011-05-05 13:52:32 +0100881 intptr_t* GetFrameSlotPointer(unsigned offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000882 DCHECK(offset < frame_size_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100883 return reinterpret_cast<intptr_t*>(
884 reinterpret_cast<Address>(this) + frame_content_offset() + offset);
885 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100886
887 int ComputeFixedSize();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100888};
889
890
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891class DeoptimizerData {
892 public:
893 explicit DeoptimizerData(MemoryAllocator* allocator);
894 ~DeoptimizerData();
895
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000896 private:
897 MemoryAllocator* allocator_;
Ben Murdochda12d292016-06-02 14:46:10 +0100898 int deopt_entry_code_entries_[Deoptimizer::kLastBailoutType + 1];
899 MemoryChunk* deopt_entry_code_[Deoptimizer::kLastBailoutType + 1];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000900
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000901 Deoptimizer* current_;
902
903 friend class Deoptimizer;
904
905 DISALLOW_COPY_AND_ASSIGN(DeoptimizerData);
906};
907
908
Ben Murdochb0fe1622011-05-05 13:52:32 +0100909class TranslationBuffer BASE_EMBEDDED {
910 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000911 explicit TranslationBuffer(Zone* zone) : contents_(256, zone) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100912
913 int CurrentIndex() const { return contents_.length(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000914 void Add(int32_t value, Zone* zone);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100915
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000916 Handle<ByteArray> CreateByteArray(Factory* factory);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100917
918 private:
919 ZoneList<uint8_t> contents_;
920};
921
922
923class TranslationIterator BASE_EMBEDDED {
924 public:
925 TranslationIterator(ByteArray* buffer, int index)
926 : buffer_(buffer), index_(index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000927 DCHECK(index >= 0 && index < buffer->length());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100928 }
929
930 int32_t Next();
931
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000932 bool HasNext() const { return index_ < buffer_->length(); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100933
934 void Skip(int n) {
935 for (int i = 0; i < n; i++) Next();
936 }
937
938 private:
939 ByteArray* buffer_;
940 int index_;
941};
942
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000943#define TRANSLATION_OPCODE_LIST(V) \
944 V(BEGIN) \
945 V(JS_FRAME) \
946 V(INTERPRETED_FRAME) \
947 V(CONSTRUCT_STUB_FRAME) \
948 V(GETTER_STUB_FRAME) \
949 V(SETTER_STUB_FRAME) \
950 V(ARGUMENTS_ADAPTOR_FRAME) \
Ben Murdochda12d292016-06-02 14:46:10 +0100951 V(TAIL_CALLER_FRAME) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000952 V(COMPILED_STUB_FRAME) \
953 V(DUPLICATED_OBJECT) \
954 V(ARGUMENTS_OBJECT) \
955 V(CAPTURED_OBJECT) \
956 V(REGISTER) \
957 V(INT32_REGISTER) \
958 V(UINT32_REGISTER) \
959 V(BOOL_REGISTER) \
960 V(DOUBLE_REGISTER) \
961 V(STACK_SLOT) \
962 V(INT32_STACK_SLOT) \
963 V(UINT32_STACK_SLOT) \
964 V(BOOL_STACK_SLOT) \
965 V(DOUBLE_STACK_SLOT) \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100966 V(LITERAL)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000967
Ben Murdochb0fe1622011-05-05 13:52:32 +0100968class Translation BASE_EMBEDDED {
969 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000970#define DECLARE_TRANSLATION_OPCODE_ENUM(item) item,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100971 enum Opcode {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000972 TRANSLATION_OPCODE_LIST(DECLARE_TRANSLATION_OPCODE_ENUM)
973 LAST = LITERAL
Ben Murdochb0fe1622011-05-05 13:52:32 +0100974 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000975#undef DECLARE_TRANSLATION_OPCODE_ENUM
Ben Murdochb0fe1622011-05-05 13:52:32 +0100976
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000977 Translation(TranslationBuffer* buffer, int frame_count, int jsframe_count,
978 Zone* zone)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100979 : buffer_(buffer),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000980 index_(buffer->CurrentIndex()),
981 zone_(zone) {
982 buffer_->Add(BEGIN, zone);
983 buffer_->Add(frame_count, zone);
984 buffer_->Add(jsframe_count, zone);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100985 }
986
987 int index() const { return index_; }
988
989 // Commands.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000990 void BeginJSFrame(BailoutId node_id, int literal_id, unsigned height);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000991 void BeginInterpretedFrame(BailoutId bytecode_offset, int literal_id,
992 unsigned height);
993 void BeginCompiledStubFrame(int height);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100994 void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
Ben Murdochda12d292016-06-02 14:46:10 +0100995 void BeginTailCallerFrame(int literal_id);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100996 void BeginConstructStubFrame(int literal_id, unsigned height);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000997 void BeginGetterStubFrame(int literal_id);
998 void BeginSetterStubFrame(int literal_id);
999 void BeginArgumentsObject(int args_length);
1000 void BeginCapturedObject(int length);
1001 void DuplicateObject(int object_index);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001002 void StoreRegister(Register reg);
1003 void StoreInt32Register(Register reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001004 void StoreUint32Register(Register reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 void StoreBoolRegister(Register reg);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001006 void StoreDoubleRegister(DoubleRegister reg);
1007 void StoreStackSlot(int index);
1008 void StoreInt32StackSlot(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001009 void StoreUint32StackSlot(int index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001010 void StoreBoolStackSlot(int index);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001011 void StoreDoubleStackSlot(int index);
1012 void StoreLiteral(int literal_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001013 void StoreArgumentsObject(bool args_known, int args_index, int args_length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001014 void StoreJSFrameFunction();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001015
1016 Zone* zone() const { return zone_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001017
1018 static int NumberOfOperandsFor(Opcode opcode);
1019
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001020#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001021 static const char* StringFor(Opcode opcode);
1022#endif
1023
1024 private:
1025 TranslationBuffer* buffer_;
1026 int index_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001027 Zone* zone_;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001028};
1029
1030
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001031class MaterializedObjectStore {
1032 public:
1033 explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) {
1034 }
1035
1036 Handle<FixedArray> Get(Address fp);
1037 void Set(Address fp, Handle<FixedArray> materialized_objects);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001038 bool Remove(Address fp);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001039
1040 private:
1041 Isolate* isolate() { return isolate_; }
1042 Handle<FixedArray> GetStackEntries();
1043 Handle<FixedArray> EnsureStackEntries(int size);
1044
1045 int StackIdToIndex(Address fp);
1046
1047 Isolate* isolate_;
1048 List<Address> frame_fps_;
Ben Murdoch8b112d22011-06-08 16:22:53 +01001049};
1050
1051
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001052// Class used to represent an unoptimized frame when the debugger
1053// needs to inspect a frame that is part of an optimized frame. The
1054// internally used FrameDescription objects are not GC safe so for use
1055// by the debugger frame information is copied to an object of this type.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001056// Represents parameters in unadapted form so their number might mismatch
1057// formal parameter count.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001058class DeoptimizedFrameInfo : public Malloced {
1059 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001060 DeoptimizedFrameInfo(TranslatedState* state,
1061 TranslatedState::iterator frame_it, Isolate* isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001062
1063 // Return the number of incoming arguments.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001064 int parameters_count() { return static_cast<int>(parameters_.size()); }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001065
1066 // Return the height of the expression stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001067 int expression_count() { return static_cast<int>(expression_stack_.size()); }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001068
1069 // Get the frame function.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001070 Handle<JSFunction> GetFunction() { return function_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001071
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001072 // Get the frame context.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001073 Handle<Object> GetContext() { return context_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001074
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001075 // Check if this frame is preceded by construct stub frame. The bottom-most
1076 // inlined frame might still be called by an uninlined construct stub.
1077 bool HasConstructStub() {
1078 return has_construct_stub_;
1079 }
1080
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001081 // Get an incoming argument.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001082 Handle<Object> GetParameter(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001083 DCHECK(0 <= index && index < parameters_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001084 return parameters_[index];
1085 }
1086
1087 // Get an expression from the expression stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001088 Handle<Object> GetExpression(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001089 DCHECK(0 <= index && index < expression_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001090 return expression_stack_[index];
1091 }
1092
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001093 int GetSourcePosition() {
1094 return source_position_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001095 }
1096
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001097 private:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001098 // Set an incoming argument.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001099 void SetParameter(int index, Handle<Object> obj) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001100 DCHECK(0 <= index && index < parameters_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001101 parameters_[index] = obj;
1102 }
1103
1104 // Set an expression on the expression stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001105 void SetExpression(int index, Handle<Object> obj) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001106 DCHECK(0 <= index && index < expression_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001107 expression_stack_[index] = obj;
1108 }
1109
Ben Murdoch097c5b22016-05-18 11:27:45 +01001110 Handle<JSFunction> function_;
1111 Handle<Object> context_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001112 bool has_construct_stub_;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001113 std::vector<Handle<Object> > parameters_;
1114 std::vector<Handle<Object> > expression_stack_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001115 int source_position_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001116
1117 friend class Deoptimizer;
1118};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001119
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001120} // namespace internal
1121} // namespace v8
Ben Murdochb0fe1622011-05-05 13:52:32 +01001122
1123#endif // V8_DEOPTIMIZER_H_