blob: db204066ca194a79cdc24e22a190def88a3f4d3e [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,
Ben Murdoch61f157c2016-09-16 13:49:30 +010042 kFloat,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043 kDouble,
44 kCapturedObject, // Object captured by the escape analysis.
45 // The number of nested objects can be obtained
46 // with the DeferredObjectLength() method
47 // (the values of the nested objects follow
48 // this value in the depth-first order.)
49 kDuplicatedObject, // Duplicated object of a deferred object.
50 kArgumentsObject // Arguments object - only used to keep indexing
51 // in sync, it should not be materialized.
52 };
53
54 TranslatedValue(TranslatedState* container, Kind kind)
55 : kind_(kind), container_(container) {}
56 Kind kind() const { return kind_; }
57 void Handlify();
58 int GetChildrenCount() const;
59
60 static TranslatedValue NewArgumentsObject(TranslatedState* container,
61 int length, int object_index);
62 static TranslatedValue NewDeferredObject(TranslatedState* container,
63 int length, int object_index);
64 static TranslatedValue NewDuplicateObject(TranslatedState* container, int id);
Ben Murdoch61f157c2016-09-16 13:49:30 +010065 static TranslatedValue NewFloat(TranslatedState* container, float value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066 static TranslatedValue NewDouble(TranslatedState* container, double value);
67 static TranslatedValue NewInt32(TranslatedState* container, int32_t value);
68 static TranslatedValue NewUInt32(TranslatedState* container, uint32_t value);
69 static TranslatedValue NewBool(TranslatedState* container, uint32_t value);
70 static TranslatedValue NewTagged(TranslatedState* container, Object* literal);
71 static TranslatedValue NewInvalid(TranslatedState* container);
72
73 Isolate* isolate() const;
74 void MaterializeSimple();
75
76 Kind kind_;
77 TranslatedState* container_; // This is only needed for materialization of
78 // objects and constructing handles (to get
79 // to the isolate).
80
81 MaybeHandle<Object> value_; // Before handlification, this is always null,
82 // after materialization it is never null,
83 // in between it is only null if the value needs
84 // to be materialized.
85
86 struct MaterializedObjectInfo {
87 int id_;
88 int length_; // Applies only to kArgumentsObject or kCapturedObject kinds.
89 };
90
91 union {
92 // kind kTagged. After handlification it is always nullptr.
93 Object* raw_literal_;
94 // kind is kUInt32 or kBoolBit.
95 uint32_t uint32_value_;
96 // kind is kInt32.
97 int32_t int32_value_;
Ben Murdoch61f157c2016-09-16 13:49:30 +010098 // kind is kFloat
99 float float_value_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000100 // kind is kDouble
101 double double_value_;
102 // kind is kDuplicatedObject or kArgumentsObject or kCapturedObject.
103 MaterializedObjectInfo materialization_info_;
104 };
105
106 // Checked accessors for the union members.
107 Object* raw_literal() const;
108 int32_t int32_value() const;
109 uint32_t uint32_value() const;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100110 float float_value() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000111 double double_value() const;
112 int object_length() const;
113 int object_index() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000114};
115
116
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117class TranslatedFrame {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000119 enum Kind {
120 kFunction,
121 kInterpretedFunction,
122 kGetter,
123 kSetter,
Ben Murdochda12d292016-06-02 14:46:10 +0100124 kTailCallerFunction,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 kArgumentsAdaptor,
126 kConstructStub,
127 kCompiledStub,
128 kInvalid
129 };
Ben Murdoch8b112d22011-06-08 16:22:53 +0100130
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131 int GetValueCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000132
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133 Kind kind() const { return kind_; }
134 BailoutId node_id() const { return node_id_; }
135 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
136 int height() const { return height_; }
137
Ben Murdoch097c5b22016-05-18 11:27:45 +0100138 SharedFunctionInfo* raw_shared_info() const {
139 CHECK_NOT_NULL(raw_shared_info_);
140 return raw_shared_info_;
141 }
142
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143 class iterator {
144 public:
145 iterator& operator++() {
146 AdvanceIterator(&position_);
147 return *this;
148 }
149
150 iterator operator++(int) {
151 iterator original(position_);
152 AdvanceIterator(&position_);
153 return original;
154 }
155
156 bool operator==(const iterator& other) const {
157 return position_ == other.position_;
158 }
159 bool operator!=(const iterator& other) const { return !(*this == other); }
160
161 TranslatedValue& operator*() { return (*position_); }
162 TranslatedValue* operator->() { return &(*position_); }
163
164 private:
165 friend TranslatedFrame;
166
167 explicit iterator(std::deque<TranslatedValue>::iterator position)
168 : position_(position) {}
169
170 std::deque<TranslatedValue>::iterator position_;
171 };
172
173 typedef TranslatedValue& reference;
174 typedef TranslatedValue const& const_reference;
175
176 iterator begin() { return iterator(values_.begin()); }
177 iterator end() { return iterator(values_.end()); }
178
179 reference front() { return values_.front(); }
180 const_reference front() const { return values_.front(); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100181
182 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183 friend class TranslatedState;
184
185 // Constructor static methods.
186 static TranslatedFrame JSFrame(BailoutId node_id,
187 SharedFunctionInfo* shared_info, int height);
188 static TranslatedFrame InterpretedFrame(BailoutId bytecode_offset,
189 SharedFunctionInfo* shared_info,
190 int height);
191 static TranslatedFrame AccessorFrame(Kind kind,
192 SharedFunctionInfo* shared_info);
193 static TranslatedFrame ArgumentsAdaptorFrame(SharedFunctionInfo* shared_info,
194 int height);
Ben Murdochda12d292016-06-02 14:46:10 +0100195 static TranslatedFrame TailCallerFrame(SharedFunctionInfo* shared_info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000196 static TranslatedFrame ConstructStubFrame(SharedFunctionInfo* shared_info,
197 int height);
198 static TranslatedFrame CompiledStubFrame(int height, Isolate* isolate) {
199 return TranslatedFrame(kCompiledStub, isolate, nullptr, height);
200 }
201 static TranslatedFrame InvalidFrame() {
202 return TranslatedFrame(kInvalid, nullptr);
203 }
204
205 static void AdvanceIterator(std::deque<TranslatedValue>::iterator* iter);
206
207 TranslatedFrame(Kind kind, Isolate* isolate,
208 SharedFunctionInfo* shared_info = nullptr, int height = 0)
209 : kind_(kind),
210 node_id_(BailoutId::None()),
211 raw_shared_info_(shared_info),
212 height_(height),
213 isolate_(isolate) {}
214
215
216 void Add(const TranslatedValue& value) { values_.push_back(value); }
217 void Handlify();
218
219 Kind kind_;
220 BailoutId node_id_;
221 SharedFunctionInfo* raw_shared_info_;
222 Handle<SharedFunctionInfo> shared_info_;
223 int height_;
224 Isolate* isolate_;
225
226 typedef std::deque<TranslatedValue> ValuesContainer;
227
228 ValuesContainer values_;
229};
230
231
232// Auxiliary class for translating deoptimization values.
233// Typical usage sequence:
234//
235// 1. Construct the instance. This will involve reading out the translations
236// and resolving them to values using the supplied frame pointer and
237// machine state (registers). This phase is guaranteed not to allocate
238// and not to use any HandleScope. Any object pointers will be stored raw.
239//
240// 2. Handlify pointers. This will convert all the raw pointers to handles.
241//
242// 3. Reading out the frame values.
243//
244// Note: After the instance is constructed, it is possible to iterate over
245// the values eagerly.
246
247class TranslatedState {
248 public:
249 TranslatedState();
250 explicit TranslatedState(JavaScriptFrame* frame);
251
252 void Prepare(bool has_adapted_arguments, Address stack_frame_pointer);
253
254 // Store newly materialized values into the isolate.
255 void StoreMaterializedValuesAndDeopt();
256
257 typedef std::vector<TranslatedFrame>::iterator iterator;
258 iterator begin() { return frames_.begin(); }
259 iterator end() { return frames_.end(); }
260
261 typedef std::vector<TranslatedFrame>::const_iterator const_iterator;
262 const_iterator begin() const { return frames_.begin(); }
263 const_iterator end() const { return frames_.end(); }
264
265 std::vector<TranslatedFrame>& frames() { return frames_; }
266
267 TranslatedFrame* GetArgumentsInfoFromJSFrameIndex(int jsframe_index,
268 int* arguments_count);
269
270 Isolate* isolate() { return isolate_; }
271
272 void Init(Address input_frame_pointer, TranslationIterator* iterator,
273 FixedArray* literal_array, RegisterValues* registers,
274 FILE* trace_file);
275
276 private:
277 friend TranslatedValue;
278
279 TranslatedFrame CreateNextTranslatedFrame(TranslationIterator* iterator,
280 FixedArray* literal_array,
281 Address fp,
282 FILE* trace_file);
283 TranslatedValue CreateNextTranslatedValue(int frame_index, int value_index,
284 TranslationIterator* iterator,
285 FixedArray* literal_array,
286 Address fp,
287 RegisterValues* registers,
288 FILE* trace_file);
289
290 void UpdateFromPreviouslyMaterializedObjects();
291 Handle<Object> MaterializeAt(int frame_index, int* value_index);
292 Handle<Object> MaterializeObjectAt(int object_index);
293 bool GetAdaptedArguments(Handle<JSObject>* result, int frame_index);
294
295 static uint32_t GetUInt32Slot(Address fp, int slot_index);
296
297 std::vector<TranslatedFrame> frames_;
298 Isolate* isolate_;
299 Address stack_frame_pointer_;
300 bool has_adapted_arguments_;
301
302 struct ObjectPosition {
303 int frame_index_;
304 int value_index_;
305 };
306 std::deque<ObjectPosition> object_positions_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100307};
308
309
310class OptimizedFunctionVisitor BASE_EMBEDDED {
311 public:
312 virtual ~OptimizedFunctionVisitor() {}
313
314 // Function which is called before iteration of any optimized functions
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000315 // from given native context.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100316 virtual void EnterContext(Context* context) = 0;
317
318 virtual void VisitFunction(JSFunction* function) = 0;
319
320 // Function which is called after iteration of all optimized functions
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000321 // from given native context.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100322 virtual void LeaveContext(Context* context) = 0;
323};
324
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000325#define DEOPT_MESSAGES_LIST(V) \
326 V(kAccessCheck, "Access check needed") \
327 V(kNoReason, "no reason") \
328 V(kConstantGlobalVariableAssignment, "Constant global variable assignment") \
329 V(kConversionOverflow, "conversion overflow") \
330 V(kDivisionByZero, "division by zero") \
331 V(kElementsKindUnhandledInKeyedLoadGenericStub, \
332 "ElementsKind unhandled in KeyedLoadGenericStub") \
333 V(kExpectedHeapNumber, "Expected heap number") \
334 V(kExpectedSmi, "Expected smi") \
335 V(kForcedDeoptToRuntime, "Forced deopt to runtime") \
336 V(kHole, "hole") \
337 V(kHoleyArrayDespitePackedElements_kindFeedback, \
338 "Holey array despite packed elements_kind feedback") \
339 V(kInstanceMigrationFailed, "instance migration failed") \
340 V(kInsufficientTypeFeedbackForCallWithArguments, \
341 "Insufficient type feedback for call with arguments") \
Ben Murdoch61f157c2016-09-16 13:49:30 +0100342 V(kFastPathFailed, "Falling off the fast path") \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343 V(kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation, \
344 "Insufficient type feedback for combined type of binary operation") \
345 V(kInsufficientTypeFeedbackForGenericNamedAccess, \
346 "Insufficient type feedback for generic named access") \
347 V(kInsufficientTypeFeedbackForKeyedLoad, \
348 "Insufficient type feedback for keyed load") \
349 V(kInsufficientTypeFeedbackForKeyedStore, \
350 "Insufficient type feedback for keyed store") \
351 V(kInsufficientTypeFeedbackForLHSOfBinaryOperation, \
352 "Insufficient type feedback for LHS of binary operation") \
353 V(kInsufficientTypeFeedbackForRHSOfBinaryOperation, \
354 "Insufficient type feedback for RHS of binary operation") \
355 V(kKeyIsNegative, "key is negative") \
356 V(kLiteralsWereDisposed, "literals have been disposed") \
357 V(kLostPrecision, "lost precision") \
358 V(kLostPrecisionOrNaN, "lost precision or NaN") \
359 V(kMementoFound, "memento found") \
360 V(kMinusZero, "minus zero") \
361 V(kNaN, "NaN") \
362 V(kNegativeKeyEncountered, "Negative key encountered") \
363 V(kNegativeValue, "negative value") \
364 V(kNoCache, "no cache") \
365 V(kNonStrictElementsInKeyedLoadGenericStub, \
366 "non-strict elements in KeyedLoadGenericStub") \
367 V(kNotADateObject, "not a date object") \
368 V(kNotAHeapNumber, "not a heap number") \
369 V(kNotAHeapNumberUndefinedBoolean, "not a heap number/undefined/true/false") \
370 V(kNotAHeapNumberUndefined, "not a heap number/undefined") \
371 V(kNotAJavaScriptObject, "not a JavaScript object") \
372 V(kNotASmi, "not a Smi") \
373 V(kNull, "null") \
374 V(kOutOfBounds, "out of bounds") \
375 V(kOutsideOfRange, "Outside of range") \
376 V(kOverflow, "overflow") \
377 V(kProxy, "proxy") \
378 V(kReceiverWasAGlobalObject, "receiver was a global object") \
379 V(kSmi, "Smi") \
380 V(kTooManyArguments, "too many arguments") \
381 V(kTooManyUndetectableTypes, "Too many undetectable types") \
382 V(kTracingElementsTransitions, "Tracing elements transitions") \
383 V(kTypeMismatchBetweenFeedbackAndConstant, \
384 "Type mismatch between feedback and constant") \
385 V(kUndefined, "undefined") \
386 V(kUnexpectedCellContentsInConstantGlobalStore, \
387 "Unexpected cell contents in constant global store") \
388 V(kUnexpectedCellContentsInGlobalStore, \
389 "Unexpected cell contents in global store") \
390 V(kUnexpectedObject, "unexpected object") \
391 V(kUnexpectedRHSOfBinaryOperation, "Unexpected RHS of binary operation") \
392 V(kUninitializedBoilerplateInFastClone, \
393 "Uninitialized boilerplate in fast clone") \
394 V(kUninitializedBoilerplateLiterals, "Uninitialized boilerplate literals") \
395 V(kUnknownMapInPolymorphicAccess, "Unknown map in polymorphic access") \
396 V(kUnknownMapInPolymorphicCall, "Unknown map in polymorphic call") \
397 V(kUnknownMapInPolymorphicElementAccess, \
398 "Unknown map in polymorphic element access") \
399 V(kUnknownMap, "Unknown map") \
400 V(kValueMismatch, "value mismatch") \
401 V(kWrongInstanceType, "wrong instance type") \
402 V(kWrongMap, "wrong map") \
403 V(kUndefinedOrNullInForIn, "null or undefined in for-in") \
404 V(kUndefinedOrNullInToObject, "null or undefined in ToObject")
405
Ben Murdochb0fe1622011-05-05 13:52:32 +0100406class Deoptimizer : public Malloced {
407 public:
Ben Murdochda12d292016-06-02 14:46:10 +0100408 enum BailoutType { EAGER, LAZY, SOFT, kLastBailoutType = SOFT };
Ben Murdochb0fe1622011-05-05 13:52:32 +0100409
Ben Murdochc5610432016-08-08 18:44:38 +0100410 enum class BailoutState {
411 NO_REGISTERS,
412 TOS_REGISTER,
413 };
414
415 static const char* BailoutStateToString(BailoutState state) {
416 switch (state) {
417 case BailoutState::NO_REGISTERS:
418 return "NO_REGISTERS";
419 case BailoutState::TOS_REGISTER:
420 return "TOS_REGISTER";
421 }
422 UNREACHABLE();
423 return nullptr;
424 }
425
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000426#define DEOPT_MESSAGES_CONSTANTS(C, T) C,
427 enum DeoptReason {
428 DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_CONSTANTS) kLastDeoptReason
429 };
430#undef DEOPT_MESSAGES_CONSTANTS
431 static const char* GetDeoptReason(DeoptReason deopt_reason);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000433 struct DeoptInfo {
Ben Murdochc5610432016-08-08 18:44:38 +0100434 DeoptInfo(SourcePosition position, DeoptReason deopt_reason, int deopt_id)
435 : position(position), deopt_reason(deopt_reason), deopt_id(deopt_id) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000436
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000437 SourcePosition position;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000438 DeoptReason deopt_reason;
Ben Murdochc5610432016-08-08 18:44:38 +0100439 int deopt_id;
440
441 static const int kNoDeoptId = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000442 };
443
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000444 static DeoptInfo GetDeoptInfo(Code* code, byte* from);
445
Ben Murdochc5610432016-08-08 18:44:38 +0100446 static int ComputeSourcePosition(SharedFunctionInfo* shared,
447 BailoutId node_id);
448
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000449 struct JumpTableEntry : public ZoneObject {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000450 inline JumpTableEntry(Address entry, const DeoptInfo& deopt_info,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451 Deoptimizer::BailoutType type, bool frame)
452 : label(),
453 address(entry),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000454 deopt_info(deopt_info),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000455 bailout_type(type),
456 needs_frame(frame) {}
457
458 bool IsEquivalentTo(const JumpTableEntry& other) const {
459 return address == other.address && bailout_type == other.bailout_type &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 needs_frame == other.needs_frame;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000461 }
462
463 Label label;
464 Address address;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000465 DeoptInfo deopt_info;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000466 Deoptimizer::BailoutType bailout_type;
467 bool needs_frame;
468 };
469
470 static bool TraceEnabledFor(BailoutType deopt_type,
471 StackFrame::Type frame_type);
472 static const char* MessageFor(BailoutType type);
473
Ben Murdochb0fe1622011-05-05 13:52:32 +0100474 int output_count() const { return output_count_; }
475
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000476 Handle<JSFunction> function() const { return Handle<JSFunction>(function_); }
477 Handle<Code> compiled_code() const { return Handle<Code>(compiled_code_); }
478 BailoutType bailout_type() const { return bailout_type_; }
479
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100480 // Number of created JS frames. Not all created frames are necessarily JS.
481 int jsframe_count() const { return jsframe_count_; }
482
Ben Murdochb0fe1622011-05-05 13:52:32 +0100483 static Deoptimizer* New(JSFunction* function,
484 BailoutType type,
485 unsigned bailout_id,
486 Address from,
Steve Block44f0eee2011-05-26 01:26:41 +0100487 int fp_to_sp_delta,
488 Isolate* isolate);
489 static Deoptimizer* Grab(Isolate* isolate);
490
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000491 // The returned object with information on the optimized frame needs to be
492 // freed before another one can be generated.
493 static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100494 int jsframe_index,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000495 Isolate* isolate);
496 static void DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
497 Isolate* isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000498
Steve Block44f0eee2011-05-26 01:26:41 +0100499 // Makes sure that there is enough room in the relocation
500 // information of a code object to perform lazy deoptimization
501 // patching. If there is not enough room a new relocation
502 // information object is allocated and comments are added until it
503 // is big enough.
504 static void EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100505
506 // Deoptimize the function now. Its current optimized code will never be run
507 // again and any activations of the optimized code will get deoptimized when
508 // execution returns.
509 static void DeoptimizeFunction(JSFunction* function);
510
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511 // Deoptimize all code in the given isolate.
512 static void DeoptimizeAll(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100513
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000514 // Deoptimizes all optimized code that has been previously marked
515 // (via code->set_marked_for_deoptimization) and unlinks all functions that
516 // refer to that code.
517 static void DeoptimizeMarkedCode(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100518
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000519 // Visit all the known optimized functions in a given isolate.
520 static void VisitAllOptimizedFunctions(
521 Isolate* isolate, OptimizedFunctionVisitor* visitor);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100522
Steve Block1e0659c2011-05-24 12:43:12 +0100523 // The size in bytes of the code required at a lazy deopt patch site.
524 static int patch_size();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100525
Ben Murdochb0fe1622011-05-05 13:52:32 +0100526 ~Deoptimizer();
527
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000528 void MaterializeHeapObjects(JavaScriptFrameIterator* it);
529
Ben Murdoch8b112d22011-06-08 16:22:53 +0100530 static void ComputeOutputFrames(Deoptimizer* deoptimizer);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100531
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532
533 enum GetEntryMode {
534 CALCULATE_ENTRY_ADDRESS,
535 ENSURE_ENTRY_CODE
536 };
537
538
539 static Address GetDeoptimizationEntry(
540 Isolate* isolate,
541 int id,
542 BailoutType type,
543 GetEntryMode mode = ENSURE_ENTRY_CODE);
544 static int GetDeoptimizationId(Isolate* isolate,
545 Address addr,
546 BailoutType type);
Steve Block9fac8402011-05-12 15:51:54 +0100547 static int GetOutputInfo(DeoptimizationOutputData* data,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000548 BailoutId node_id,
Steve Block9fac8402011-05-12 15:51:54 +0100549 SharedFunctionInfo* shared);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100550
Ben Murdochb0fe1622011-05-05 13:52:32 +0100551 // Code generation support.
552 static int input_offset() { return OFFSET_OF(Deoptimizer, input_); }
553 static int output_count_offset() {
554 return OFFSET_OF(Deoptimizer, output_count_);
555 }
556 static int output_offset() { return OFFSET_OF(Deoptimizer, output_); }
557
Ben Murdochda12d292016-06-02 14:46:10 +0100558 static int caller_frame_top_offset() {
559 return OFFSET_OF(Deoptimizer, caller_frame_top_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000560 }
561
Steve Block44f0eee2011-05-26 01:26:41 +0100562 static int GetDeoptimizedCodeCount(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100563
564 static const int kNotDeoptimizationEntry = -1;
565
566 // Generators for the deoptimization entry code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000567 class TableEntryGenerator BASE_EMBEDDED {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100568 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569 TableEntryGenerator(MacroAssembler* masm, BailoutType type, int count)
570 : masm_(masm), type_(type), count_(count) {}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100571
572 void Generate();
573
574 protected:
575 MacroAssembler* masm() const { return masm_; }
576 BailoutType type() const { return type_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000577 Isolate* isolate() const { return masm_->isolate(); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 void GeneratePrologue();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100580
581 private:
582 int count() const { return count_; }
583
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000584 MacroAssembler* masm_;
585 Deoptimizer::BailoutType type_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100586 int count_;
587 };
588
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100589 int ConvertJSFrameIndexToFrameIndex(int jsframe_index);
590
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000591 static size_t GetMaxDeoptTableSize();
592
593 static void EnsureCodeForDeoptimizationEntry(Isolate* isolate,
594 BailoutType type,
595 int max_entry_id);
596
597 Isolate* isolate() const { return isolate_; }
598
Ben Murdochb0fe1622011-05-05 13:52:32 +0100599 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600 static const int kMinNumberOfEntries = 64;
601 static const int kMaxNumberOfEntries = 16384;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100602
Steve Block44f0eee2011-05-26 01:26:41 +0100603 Deoptimizer(Isolate* isolate,
604 JSFunction* function,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100605 BailoutType type,
606 unsigned bailout_id,
607 Address from,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000608 int fp_to_sp_delta,
609 Code* optimized_code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000610 Code* FindOptimizedCode(JSFunction* function, Code* optimized_code);
611 void PrintFunctionName();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100612 void DeleteFrameDescriptions();
613
614 void DoComputeOutputFrames();
Ben Murdochda12d292016-06-02 14:46:10 +0100615 void DoComputeJSFrame(TranslatedFrame* translated_frame, int frame_index,
616 bool goto_catch_handler);
617 void DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
618 int frame_index, bool goto_catch_handler);
619 void DoComputeArgumentsAdaptorFrame(TranslatedFrame* translated_frame,
620 int frame_index);
621 void DoComputeTailCallerFrame(TranslatedFrame* translated_frame,
622 int frame_index);
623 void DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
624 int frame_index);
625 void DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
626 int frame_index, bool is_setter_stub_frame);
627 void DoComputeCompiledStubFrame(TranslatedFrame* translated_frame,
628 int frame_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000630 void WriteTranslatedValueToOutput(
631 TranslatedFrame::iterator* iterator, int* input_index, int frame_index,
632 unsigned output_offset, const char* debug_hint_string = nullptr,
633 Address output_address_for_materialization = nullptr);
634 void WriteValueToOutput(Object* value, int input_index, int frame_index,
635 unsigned output_offset,
636 const char* debug_hint_string);
637 void DebugPrintOutputSlot(intptr_t value, int frame_index,
638 unsigned output_offset,
639 const char* debug_hint_string);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100640
Ben Murdochda12d292016-06-02 14:46:10 +0100641 unsigned ComputeInputFrameAboveFpFixedSize() const;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100642 unsigned ComputeInputFrameSize() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100643 static unsigned ComputeJavascriptFixedSize(SharedFunctionInfo* shared);
644 static unsigned ComputeInterpretedFixedSize(SharedFunctionInfo* shared);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100645
Ben Murdoch097c5b22016-05-18 11:27:45 +0100646 static unsigned ComputeIncomingArgumentSize(SharedFunctionInfo* shared);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000647 static unsigned ComputeOutgoingArgumentSize(Code* code, unsigned bailout_id);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100648
649 Object* ComputeLiteral(int index) const;
650
Ben Murdochb0fe1622011-05-05 13:52:32 +0100651 static void GenerateDeoptimizationEntries(
652 MacroAssembler* masm, int count, BailoutType type);
653
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000654 // Marks all the code in the given context for deoptimization.
655 static void MarkAllCodeForContext(Context* native_context);
656
657 // Visit all the known optimized functions in a given context.
658 static void VisitAllOptimizedFunctionsForContext(
659 Context* context, OptimizedFunctionVisitor* visitor);
660
661 // Deoptimizes all code marked in the given context.
662 static void DeoptimizeMarkedCodeForContext(Context* native_context);
663
664 // Patch the given code so that it will deoptimize itself.
665 static void PatchCodeForDeoptimization(Isolate* isolate, Code* code);
666
667 // Searches the list of known deoptimizing code for a Code object
668 // containing the given address (which is supposedly faster than
669 // searching all code objects).
670 Code* FindDeoptimizingCode(Address addr);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100671
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000672 // Fill the given output frame's registers to contain the failure handler
673 // address and the number of parameters for a stub failure trampoline.
674 void SetPlatformCompiledStubRegisters(FrameDescription* output_frame,
675 CodeStubDescriptor* desc);
676
677 // Fill the given output frame's double registers with the original values
678 // from the input frame's double registers.
679 void CopyDoubleRegisters(FrameDescription* output_frame);
680
Steve Block44f0eee2011-05-26 01:26:41 +0100681 Isolate* isolate_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100682 JSFunction* function_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000683 Code* compiled_code_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100684 unsigned bailout_id_;
685 BailoutType bailout_type_;
686 Address from_;
687 int fp_to_sp_delta_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100688 bool deoptimizing_throw_;
689 int catch_handler_data_;
690 int catch_handler_pc_offset_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100691
692 // Input frame description.
693 FrameDescription* input_;
694 // Number of output frames.
695 int output_count_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100696 // Number of output js frames.
697 int jsframe_count_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100698 // Array of output frame descriptions.
699 FrameDescription** output_;
700
Ben Murdochda12d292016-06-02 14:46:10 +0100701 // Caller frame details computed from input frame.
702 intptr_t caller_frame_top_;
703 intptr_t caller_fp_;
704 intptr_t caller_pc_;
705 intptr_t caller_constant_pool_;
706 intptr_t input_frame_context_;
707
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000708 // Key for lookup of previously materialized objects
Ben Murdochda12d292016-06-02 14:46:10 +0100709 intptr_t stack_fp_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000710
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000711 TranslatedState translated_state_;
712 struct ValueToMaterialize {
713 Address output_slot_address_;
714 TranslatedFrame::iterator value_;
715 };
716 std::vector<ValueToMaterialize> values_to_materialize_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000717
718#ifdef DEBUG
719 DisallowHeapAllocation* disallow_heap_allocation_;
720#endif // DEBUG
721
722 CodeTracer::Scope* trace_scope_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100723
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000724 static const int table_entry_size_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100725
726 friend class FrameDescription;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000727 friend class DeoptimizedFrameInfo;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100728};
729
730
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000731class RegisterValues {
732 public:
733 intptr_t GetRegister(unsigned n) const {
734#if DEBUG
735 // This convoluted DCHECK is needed to work around a gcc problem that
736 // improperly detects an array bounds overflow in optimized debug builds
737 // when using a plain DCHECK.
738 if (n >= arraysize(registers_)) {
739 DCHECK(false);
740 return 0;
741 }
742#endif
743 return registers_[n];
744 }
745
Ben Murdoch61f157c2016-09-16 13:49:30 +0100746 float GetFloatRegister(unsigned n) const {
747 DCHECK(n < arraysize(float_registers_));
748 return float_registers_[n];
749 }
750
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000751 double GetDoubleRegister(unsigned n) const {
752 DCHECK(n < arraysize(double_registers_));
753 return double_registers_[n];
754 }
755
756 void SetRegister(unsigned n, intptr_t value) {
757 DCHECK(n < arraysize(registers_));
758 registers_[n] = value;
759 }
760
Ben Murdoch61f157c2016-09-16 13:49:30 +0100761 void SetFloatRegister(unsigned n, float value) {
762 DCHECK(n < arraysize(float_registers_));
763 float_registers_[n] = value;
764 }
765
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000766 void SetDoubleRegister(unsigned n, double value) {
767 DCHECK(n < arraysize(double_registers_));
768 double_registers_[n] = value;
769 }
770
771 intptr_t registers_[Register::kNumRegisters];
Ben Murdoch61f157c2016-09-16 13:49:30 +0100772 float float_registers_[FloatRegister::kMaxNumRegisters];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000773 double double_registers_[DoubleRegister::kMaxNumRegisters];
774};
775
776
Ben Murdochb0fe1622011-05-05 13:52:32 +0100777class FrameDescription {
778 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100779 explicit FrameDescription(uint32_t frame_size, int parameter_count = 0);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100780
781 void* operator new(size_t size, uint32_t frame_size) {
Steve Block44f0eee2011-05-26 01:26:41 +0100782 // Subtracts kPointerSize, as the member frame_content_ already supplies
783 // the first element of the area to store the frame.
784 return malloc(size + frame_size - kPointerSize);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100785 }
786
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000787 void operator delete(void* pointer, uint32_t frame_size) {
788 free(pointer);
789 }
790
Ben Murdochb0fe1622011-05-05 13:52:32 +0100791 void operator delete(void* description) {
792 free(description);
793 }
794
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000795 uint32_t GetFrameSize() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000796 DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000797 return static_cast<uint32_t>(frame_size_);
798 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100799
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100800 unsigned GetOffsetFromSlotIndex(int slot_index);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100801
802 intptr_t GetFrameSlot(unsigned offset) {
803 return *GetFrameSlotPointer(offset);
804 }
805
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000806 Address GetFramePointerAddress() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100807 int fp_offset = GetFrameSize() - parameter_count() * kPointerSize -
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000808 StandardFrameConstants::kCallerSPOffset;
809 return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100810 }
811
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000812 RegisterValues* GetRegisterValues() { return &register_values_; }
813
Ben Murdochb0fe1622011-05-05 13:52:32 +0100814 void SetFrameSlot(unsigned offset, intptr_t value) {
815 *GetFrameSlotPointer(offset) = value;
816 }
817
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000818 void SetCallerPc(unsigned offset, intptr_t value);
819
820 void SetCallerFp(unsigned offset, intptr_t value);
821
822 void SetCallerConstantPool(unsigned offset, intptr_t value);
823
Ben Murdochb0fe1622011-05-05 13:52:32 +0100824 intptr_t GetRegister(unsigned n) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000825 return register_values_.GetRegister(n);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100826 }
827
828 double GetDoubleRegister(unsigned n) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000829 return register_values_.GetDoubleRegister(n);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100830 }
831
832 void SetRegister(unsigned n, intptr_t value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000833 register_values_.SetRegister(n, value);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100834 }
835
836 void SetDoubleRegister(unsigned n, double value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000837 register_values_.SetDoubleRegister(n, value);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100838 }
839
840 intptr_t GetTop() const { return top_; }
841 void SetTop(intptr_t top) { top_ = top; }
842
843 intptr_t GetPc() const { return pc_; }
844 void SetPc(intptr_t pc) { pc_ = pc; }
845
846 intptr_t GetFp() const { return fp_; }
847 void SetFp(intptr_t fp) { fp_ = fp; }
848
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100849 intptr_t GetContext() const { return context_; }
850 void SetContext(intptr_t context) { context_ = context; }
851
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000852 intptr_t GetConstantPool() const { return constant_pool_; }
853 void SetConstantPool(intptr_t constant_pool) {
854 constant_pool_ = constant_pool;
855 }
856
Ben Murdochb0fe1622011-05-05 13:52:32 +0100857 Smi* GetState() const { return state_; }
858 void SetState(Smi* state) { state_ = state; }
859
860 void SetContinuation(intptr_t pc) { continuation_ = pc; }
861
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100862 StackFrame::Type GetFrameType() const { return type_; }
863 void SetFrameType(StackFrame::Type type) { type_ = type; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000864
Ben Murdoch097c5b22016-05-18 11:27:45 +0100865 // Argument count, including receiver.
866 int parameter_count() { return parameter_count_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000867
Ben Murdochb0fe1622011-05-05 13:52:32 +0100868 static int registers_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000869 return OFFSET_OF(FrameDescription, register_values_.registers_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100870 }
871
872 static int double_registers_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000873 return OFFSET_OF(FrameDescription, register_values_.double_registers_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100874 }
875
876 static int frame_size_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000877 return offsetof(FrameDescription, frame_size_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100878 }
879
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880 static int pc_offset() { return offsetof(FrameDescription, pc_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100881
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000882 static int state_offset() { return offsetof(FrameDescription, state_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100883
884 static int continuation_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000885 return offsetof(FrameDescription, continuation_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100886 }
887
888 static int frame_content_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000889 return offsetof(FrameDescription, frame_content_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100890 }
891
892 private:
893 static const uint32_t kZapUint32 = 0xbeeddead;
894
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000895 // Frame_size_ must hold a uint32_t value. It is only a uintptr_t to
896 // keep the variable-size array frame_content_ of type intptr_t at
897 // the end of the structure aligned.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100898 uintptr_t frame_size_; // Number of bytes.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100899 int parameter_count_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000900 RegisterValues register_values_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100901 intptr_t top_;
902 intptr_t pc_;
903 intptr_t fp_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100904 intptr_t context_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000905 intptr_t constant_pool_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100906 StackFrame::Type type_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100907 Smi* state_;
908
909 // Continuation is the PC where the execution continues after
910 // deoptimizing.
911 intptr_t continuation_;
912
Steve Block44f0eee2011-05-26 01:26:41 +0100913 // This must be at the end of the object as the object is allocated larger
914 // than it's definition indicate to extend this array.
915 intptr_t frame_content_[1];
916
Ben Murdochb0fe1622011-05-05 13:52:32 +0100917 intptr_t* GetFrameSlotPointer(unsigned offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000918 DCHECK(offset < frame_size_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100919 return reinterpret_cast<intptr_t*>(
920 reinterpret_cast<Address>(this) + frame_content_offset() + offset);
921 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100922
923 int ComputeFixedSize();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100924};
925
926
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000927class DeoptimizerData {
928 public:
929 explicit DeoptimizerData(MemoryAllocator* allocator);
930 ~DeoptimizerData();
931
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000932 private:
933 MemoryAllocator* allocator_;
Ben Murdochda12d292016-06-02 14:46:10 +0100934 int deopt_entry_code_entries_[Deoptimizer::kLastBailoutType + 1];
935 MemoryChunk* deopt_entry_code_[Deoptimizer::kLastBailoutType + 1];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000936
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000937 Deoptimizer* current_;
938
939 friend class Deoptimizer;
940
941 DISALLOW_COPY_AND_ASSIGN(DeoptimizerData);
942};
943
944
Ben Murdochb0fe1622011-05-05 13:52:32 +0100945class TranslationBuffer BASE_EMBEDDED {
946 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000947 explicit TranslationBuffer(Zone* zone) : contents_(256, zone) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100948
949 int CurrentIndex() const { return contents_.length(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000950 void Add(int32_t value, Zone* zone);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100951
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000952 Handle<ByteArray> CreateByteArray(Factory* factory);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100953
954 private:
955 ZoneList<uint8_t> contents_;
956};
957
958
959class TranslationIterator BASE_EMBEDDED {
960 public:
961 TranslationIterator(ByteArray* buffer, int index)
962 : buffer_(buffer), index_(index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000963 DCHECK(index >= 0 && index < buffer->length());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100964 }
965
966 int32_t Next();
967
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000968 bool HasNext() const { return index_ < buffer_->length(); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100969
970 void Skip(int n) {
971 for (int i = 0; i < n; i++) Next();
972 }
973
974 private:
975 ByteArray* buffer_;
976 int index_;
977};
978
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000979#define TRANSLATION_OPCODE_LIST(V) \
980 V(BEGIN) \
981 V(JS_FRAME) \
982 V(INTERPRETED_FRAME) \
983 V(CONSTRUCT_STUB_FRAME) \
984 V(GETTER_STUB_FRAME) \
985 V(SETTER_STUB_FRAME) \
986 V(ARGUMENTS_ADAPTOR_FRAME) \
Ben Murdochda12d292016-06-02 14:46:10 +0100987 V(TAIL_CALLER_FRAME) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000988 V(COMPILED_STUB_FRAME) \
989 V(DUPLICATED_OBJECT) \
990 V(ARGUMENTS_OBJECT) \
991 V(CAPTURED_OBJECT) \
992 V(REGISTER) \
993 V(INT32_REGISTER) \
994 V(UINT32_REGISTER) \
995 V(BOOL_REGISTER) \
Ben Murdoch61f157c2016-09-16 13:49:30 +0100996 V(FLOAT_REGISTER) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000997 V(DOUBLE_REGISTER) \
998 V(STACK_SLOT) \
999 V(INT32_STACK_SLOT) \
1000 V(UINT32_STACK_SLOT) \
1001 V(BOOL_STACK_SLOT) \
Ben Murdoch61f157c2016-09-16 13:49:30 +01001002 V(FLOAT_STACK_SLOT) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001003 V(DOUBLE_STACK_SLOT) \
Ben Murdoch097c5b22016-05-18 11:27:45 +01001004 V(LITERAL)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001005
Ben Murdochb0fe1622011-05-05 13:52:32 +01001006class Translation BASE_EMBEDDED {
1007 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001008#define DECLARE_TRANSLATION_OPCODE_ENUM(item) item,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001009 enum Opcode {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001010 TRANSLATION_OPCODE_LIST(DECLARE_TRANSLATION_OPCODE_ENUM)
1011 LAST = LITERAL
Ben Murdochb0fe1622011-05-05 13:52:32 +01001012 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001013#undef DECLARE_TRANSLATION_OPCODE_ENUM
Ben Murdochb0fe1622011-05-05 13:52:32 +01001014
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001015 Translation(TranslationBuffer* buffer, int frame_count, int jsframe_count,
1016 Zone* zone)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001017 : buffer_(buffer),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001018 index_(buffer->CurrentIndex()),
1019 zone_(zone) {
1020 buffer_->Add(BEGIN, zone);
1021 buffer_->Add(frame_count, zone);
1022 buffer_->Add(jsframe_count, zone);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001023 }
1024
1025 int index() const { return index_; }
1026
1027 // Commands.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001028 void BeginJSFrame(BailoutId node_id, int literal_id, unsigned height);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001029 void BeginInterpretedFrame(BailoutId bytecode_offset, int literal_id,
1030 unsigned height);
1031 void BeginCompiledStubFrame(int height);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001032 void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
Ben Murdochda12d292016-06-02 14:46:10 +01001033 void BeginTailCallerFrame(int literal_id);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001034 void BeginConstructStubFrame(int literal_id, unsigned height);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001035 void BeginGetterStubFrame(int literal_id);
1036 void BeginSetterStubFrame(int literal_id);
1037 void BeginArgumentsObject(int args_length);
1038 void BeginCapturedObject(int length);
1039 void DuplicateObject(int object_index);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001040 void StoreRegister(Register reg);
1041 void StoreInt32Register(Register reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001042 void StoreUint32Register(Register reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001043 void StoreBoolRegister(Register reg);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001044 void StoreFloatRegister(FloatRegister reg);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001045 void StoreDoubleRegister(DoubleRegister reg);
1046 void StoreStackSlot(int index);
1047 void StoreInt32StackSlot(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048 void StoreUint32StackSlot(int index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001049 void StoreBoolStackSlot(int index);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001050 void StoreFloatStackSlot(int index);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001051 void StoreDoubleStackSlot(int index);
1052 void StoreLiteral(int literal_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001053 void StoreArgumentsObject(bool args_known, int args_index, int args_length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001054 void StoreJSFrameFunction();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001055
1056 Zone* zone() const { return zone_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001057
1058 static int NumberOfOperandsFor(Opcode opcode);
1059
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001060#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001061 static const char* StringFor(Opcode opcode);
1062#endif
1063
1064 private:
1065 TranslationBuffer* buffer_;
1066 int index_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001067 Zone* zone_;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001068};
1069
1070
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001071class MaterializedObjectStore {
1072 public:
1073 explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) {
1074 }
1075
1076 Handle<FixedArray> Get(Address fp);
1077 void Set(Address fp, Handle<FixedArray> materialized_objects);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001078 bool Remove(Address fp);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001079
1080 private:
1081 Isolate* isolate() { return isolate_; }
1082 Handle<FixedArray> GetStackEntries();
1083 Handle<FixedArray> EnsureStackEntries(int size);
1084
1085 int StackIdToIndex(Address fp);
1086
1087 Isolate* isolate_;
1088 List<Address> frame_fps_;
Ben Murdoch8b112d22011-06-08 16:22:53 +01001089};
1090
1091
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001092// Class used to represent an unoptimized frame when the debugger
1093// needs to inspect a frame that is part of an optimized frame. The
1094// internally used FrameDescription objects are not GC safe so for use
1095// by the debugger frame information is copied to an object of this type.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001096// Represents parameters in unadapted form so their number might mismatch
1097// formal parameter count.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001098class DeoptimizedFrameInfo : public Malloced {
1099 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001100 DeoptimizedFrameInfo(TranslatedState* state,
1101 TranslatedState::iterator frame_it, Isolate* isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001102
1103 // Return the number of incoming arguments.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001104 int parameters_count() { return static_cast<int>(parameters_.size()); }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001105
1106 // Return the height of the expression stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001107 int expression_count() { return static_cast<int>(expression_stack_.size()); }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001108
1109 // Get the frame function.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001110 Handle<JSFunction> GetFunction() { return function_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001111
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001112 // Get the frame context.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001113 Handle<Object> GetContext() { return context_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001114
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001115 // Check if this frame is preceded by construct stub frame. The bottom-most
1116 // inlined frame might still be called by an uninlined construct stub.
1117 bool HasConstructStub() {
1118 return has_construct_stub_;
1119 }
1120
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001121 // Get an incoming argument.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001122 Handle<Object> GetParameter(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001123 DCHECK(0 <= index && index < parameters_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001124 return parameters_[index];
1125 }
1126
1127 // Get an expression from the expression stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001128 Handle<Object> GetExpression(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001129 DCHECK(0 <= index && index < expression_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001130 return expression_stack_[index];
1131 }
1132
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001133 int GetSourcePosition() {
1134 return source_position_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001135 }
1136
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001137 private:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001138 // Set an incoming argument.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001139 void SetParameter(int index, Handle<Object> obj) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001140 DCHECK(0 <= index && index < parameters_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001141 parameters_[index] = obj;
1142 }
1143
1144 // Set an expression on the expression stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001145 void SetExpression(int index, Handle<Object> obj) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001146 DCHECK(0 <= index && index < expression_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001147 expression_stack_[index] = obj;
1148 }
1149
Ben Murdoch097c5b22016-05-18 11:27:45 +01001150 Handle<JSFunction> function_;
1151 Handle<Object> context_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001152 bool has_construct_stub_;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001153 std::vector<Handle<Object> > parameters_;
1154 std::vector<Handle<Object> > expression_stack_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001155 int source_position_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001156
1157 friend class Deoptimizer;
1158};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001159
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001160} // namespace internal
1161} // namespace v8
Ben Murdochb0fe1622011-05-05 13:52:32 +01001162
1163#endif // V8_DEOPTIMIZER_H_