blob: 1d413e6babf39f79a84528db163de3598d06a400 [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 Murdochc5610432016-08-08 18:44:38 +0100405 enum class BailoutState {
406 NO_REGISTERS,
407 TOS_REGISTER,
408 };
409
410 static const char* BailoutStateToString(BailoutState state) {
411 switch (state) {
412 case BailoutState::NO_REGISTERS:
413 return "NO_REGISTERS";
414 case BailoutState::TOS_REGISTER:
415 return "TOS_REGISTER";
416 }
417 UNREACHABLE();
418 return nullptr;
419 }
420
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000421#define DEOPT_MESSAGES_CONSTANTS(C, T) C,
422 enum DeoptReason {
423 DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_CONSTANTS) kLastDeoptReason
424 };
425#undef DEOPT_MESSAGES_CONSTANTS
426 static const char* GetDeoptReason(DeoptReason deopt_reason);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000428 struct DeoptInfo {
Ben Murdochc5610432016-08-08 18:44:38 +0100429 DeoptInfo(SourcePosition position, DeoptReason deopt_reason, int deopt_id)
430 : position(position), deopt_reason(deopt_reason), deopt_id(deopt_id) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000431
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000432 SourcePosition position;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000433 DeoptReason deopt_reason;
Ben Murdochc5610432016-08-08 18:44:38 +0100434 int deopt_id;
435
436 static const int kNoDeoptId = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000437 };
438
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000439 static DeoptInfo GetDeoptInfo(Code* code, byte* from);
440
Ben Murdochc5610432016-08-08 18:44:38 +0100441 static int ComputeSourcePosition(SharedFunctionInfo* shared,
442 BailoutId node_id);
443
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000444 struct JumpTableEntry : public ZoneObject {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000445 inline JumpTableEntry(Address entry, const DeoptInfo& deopt_info,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000446 Deoptimizer::BailoutType type, bool frame)
447 : label(),
448 address(entry),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000449 deopt_info(deopt_info),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000450 bailout_type(type),
451 needs_frame(frame) {}
452
453 bool IsEquivalentTo(const JumpTableEntry& other) const {
454 return address == other.address && bailout_type == other.bailout_type &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000455 needs_frame == other.needs_frame;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000456 }
457
458 Label label;
459 Address address;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 DeoptInfo deopt_info;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000461 Deoptimizer::BailoutType bailout_type;
462 bool needs_frame;
463 };
464
465 static bool TraceEnabledFor(BailoutType deopt_type,
466 StackFrame::Type frame_type);
467 static const char* MessageFor(BailoutType type);
468
Ben Murdochb0fe1622011-05-05 13:52:32 +0100469 int output_count() const { return output_count_; }
470
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000471 Handle<JSFunction> function() const { return Handle<JSFunction>(function_); }
472 Handle<Code> compiled_code() const { return Handle<Code>(compiled_code_); }
473 BailoutType bailout_type() const { return bailout_type_; }
474
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100475 // Number of created JS frames. Not all created frames are necessarily JS.
476 int jsframe_count() const { return jsframe_count_; }
477
Ben Murdochb0fe1622011-05-05 13:52:32 +0100478 static Deoptimizer* New(JSFunction* function,
479 BailoutType type,
480 unsigned bailout_id,
481 Address from,
Steve Block44f0eee2011-05-26 01:26:41 +0100482 int fp_to_sp_delta,
483 Isolate* isolate);
484 static Deoptimizer* Grab(Isolate* isolate);
485
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000486 // The returned object with information on the optimized frame needs to be
487 // freed before another one can be generated.
488 static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100489 int jsframe_index,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000490 Isolate* isolate);
491 static void DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
492 Isolate* isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000493
Steve Block44f0eee2011-05-26 01:26:41 +0100494 // Makes sure that there is enough room in the relocation
495 // information of a code object to perform lazy deoptimization
496 // patching. If there is not enough room a new relocation
497 // information object is allocated and comments are added until it
498 // is big enough.
499 static void EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100500
501 // Deoptimize the function now. Its current optimized code will never be run
502 // again and any activations of the optimized code will get deoptimized when
503 // execution returns.
504 static void DeoptimizeFunction(JSFunction* function);
505
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000506 // Deoptimize all code in the given isolate.
507 static void DeoptimizeAll(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100508
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000509 // Deoptimizes all optimized code that has been previously marked
510 // (via code->set_marked_for_deoptimization) and unlinks all functions that
511 // refer to that code.
512 static void DeoptimizeMarkedCode(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100513
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000514 // Visit all the known optimized functions in a given isolate.
515 static void VisitAllOptimizedFunctions(
516 Isolate* isolate, OptimizedFunctionVisitor* visitor);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100517
Steve Block1e0659c2011-05-24 12:43:12 +0100518 // The size in bytes of the code required at a lazy deopt patch site.
519 static int patch_size();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100520
Ben Murdochb0fe1622011-05-05 13:52:32 +0100521 ~Deoptimizer();
522
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523 void MaterializeHeapObjects(JavaScriptFrameIterator* it);
524
Ben Murdoch8b112d22011-06-08 16:22:53 +0100525 static void ComputeOutputFrames(Deoptimizer* deoptimizer);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100526
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000527
528 enum GetEntryMode {
529 CALCULATE_ENTRY_ADDRESS,
530 ENSURE_ENTRY_CODE
531 };
532
533
534 static Address GetDeoptimizationEntry(
535 Isolate* isolate,
536 int id,
537 BailoutType type,
538 GetEntryMode mode = ENSURE_ENTRY_CODE);
539 static int GetDeoptimizationId(Isolate* isolate,
540 Address addr,
541 BailoutType type);
Steve Block9fac8402011-05-12 15:51:54 +0100542 static int GetOutputInfo(DeoptimizationOutputData* data,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000543 BailoutId node_id,
Steve Block9fac8402011-05-12 15:51:54 +0100544 SharedFunctionInfo* shared);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100545
Ben Murdochb0fe1622011-05-05 13:52:32 +0100546 // Code generation support.
547 static int input_offset() { return OFFSET_OF(Deoptimizer, input_); }
548 static int output_count_offset() {
549 return OFFSET_OF(Deoptimizer, output_count_);
550 }
551 static int output_offset() { return OFFSET_OF(Deoptimizer, output_); }
552
Ben Murdochda12d292016-06-02 14:46:10 +0100553 static int caller_frame_top_offset() {
554 return OFFSET_OF(Deoptimizer, caller_frame_top_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000555 }
556
Steve Block44f0eee2011-05-26 01:26:41 +0100557 static int GetDeoptimizedCodeCount(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100558
559 static const int kNotDeoptimizationEntry = -1;
560
561 // Generators for the deoptimization entry code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000562 class TableEntryGenerator BASE_EMBEDDED {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100563 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000564 TableEntryGenerator(MacroAssembler* masm, BailoutType type, int count)
565 : masm_(masm), type_(type), count_(count) {}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100566
567 void Generate();
568
569 protected:
570 MacroAssembler* masm() const { return masm_; }
571 BailoutType type() const { return type_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000572 Isolate* isolate() const { return masm_->isolate(); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100573
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000574 void GeneratePrologue();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100575
576 private:
577 int count() const { return count_; }
578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 MacroAssembler* masm_;
580 Deoptimizer::BailoutType type_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100581 int count_;
582 };
583
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100584 int ConvertJSFrameIndexToFrameIndex(int jsframe_index);
585
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000586 static size_t GetMaxDeoptTableSize();
587
588 static void EnsureCodeForDeoptimizationEntry(Isolate* isolate,
589 BailoutType type,
590 int max_entry_id);
591
592 Isolate* isolate() const { return isolate_; }
593
Ben Murdochb0fe1622011-05-05 13:52:32 +0100594 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000595 static const int kMinNumberOfEntries = 64;
596 static const int kMaxNumberOfEntries = 16384;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100597
Steve Block44f0eee2011-05-26 01:26:41 +0100598 Deoptimizer(Isolate* isolate,
599 JSFunction* function,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100600 BailoutType type,
601 unsigned bailout_id,
602 Address from,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000603 int fp_to_sp_delta,
604 Code* optimized_code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605 Code* FindOptimizedCode(JSFunction* function, Code* optimized_code);
606 void PrintFunctionName();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100607 void DeleteFrameDescriptions();
608
609 void DoComputeOutputFrames();
Ben Murdochda12d292016-06-02 14:46:10 +0100610 void DoComputeJSFrame(TranslatedFrame* translated_frame, int frame_index,
611 bool goto_catch_handler);
612 void DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
613 int frame_index, bool goto_catch_handler);
614 void DoComputeArgumentsAdaptorFrame(TranslatedFrame* translated_frame,
615 int frame_index);
616 void DoComputeTailCallerFrame(TranslatedFrame* translated_frame,
617 int frame_index);
618 void DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
619 int frame_index);
620 void DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
621 int frame_index, bool is_setter_stub_frame);
622 void DoComputeCompiledStubFrame(TranslatedFrame* translated_frame,
623 int frame_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000625 void WriteTranslatedValueToOutput(
626 TranslatedFrame::iterator* iterator, int* input_index, int frame_index,
627 unsigned output_offset, const char* debug_hint_string = nullptr,
628 Address output_address_for_materialization = nullptr);
629 void WriteValueToOutput(Object* value, int input_index, int frame_index,
630 unsigned output_offset,
631 const char* debug_hint_string);
632 void DebugPrintOutputSlot(intptr_t value, int frame_index,
633 unsigned output_offset,
634 const char* debug_hint_string);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100635
Ben Murdochda12d292016-06-02 14:46:10 +0100636 unsigned ComputeInputFrameAboveFpFixedSize() const;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100637 unsigned ComputeInputFrameSize() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100638 static unsigned ComputeJavascriptFixedSize(SharedFunctionInfo* shared);
639 static unsigned ComputeInterpretedFixedSize(SharedFunctionInfo* shared);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100640
Ben Murdoch097c5b22016-05-18 11:27:45 +0100641 static unsigned ComputeIncomingArgumentSize(SharedFunctionInfo* shared);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000642 static unsigned ComputeOutgoingArgumentSize(Code* code, unsigned bailout_id);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100643
644 Object* ComputeLiteral(int index) const;
645
Ben Murdochb0fe1622011-05-05 13:52:32 +0100646 static void GenerateDeoptimizationEntries(
647 MacroAssembler* masm, int count, BailoutType type);
648
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000649 // Marks all the code in the given context for deoptimization.
650 static void MarkAllCodeForContext(Context* native_context);
651
652 // Visit all the known optimized functions in a given context.
653 static void VisitAllOptimizedFunctionsForContext(
654 Context* context, OptimizedFunctionVisitor* visitor);
655
656 // Deoptimizes all code marked in the given context.
657 static void DeoptimizeMarkedCodeForContext(Context* native_context);
658
659 // Patch the given code so that it will deoptimize itself.
660 static void PatchCodeForDeoptimization(Isolate* isolate, Code* code);
661
662 // Searches the list of known deoptimizing code for a Code object
663 // containing the given address (which is supposedly faster than
664 // searching all code objects).
665 Code* FindDeoptimizingCode(Address addr);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100666
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000667 // Fill the given output frame's registers to contain the failure handler
668 // address and the number of parameters for a stub failure trampoline.
669 void SetPlatformCompiledStubRegisters(FrameDescription* output_frame,
670 CodeStubDescriptor* desc);
671
672 // Fill the given output frame's double registers with the original values
673 // from the input frame's double registers.
674 void CopyDoubleRegisters(FrameDescription* output_frame);
675
Steve Block44f0eee2011-05-26 01:26:41 +0100676 Isolate* isolate_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100677 JSFunction* function_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000678 Code* compiled_code_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100679 unsigned bailout_id_;
680 BailoutType bailout_type_;
681 Address from_;
682 int fp_to_sp_delta_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100683 bool deoptimizing_throw_;
684 int catch_handler_data_;
685 int catch_handler_pc_offset_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100686
687 // Input frame description.
688 FrameDescription* input_;
689 // Number of output frames.
690 int output_count_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100691 // Number of output js frames.
692 int jsframe_count_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100693 // Array of output frame descriptions.
694 FrameDescription** output_;
695
Ben Murdochda12d292016-06-02 14:46:10 +0100696 // Caller frame details computed from input frame.
697 intptr_t caller_frame_top_;
698 intptr_t caller_fp_;
699 intptr_t caller_pc_;
700 intptr_t caller_constant_pool_;
701 intptr_t input_frame_context_;
702
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000703 // Key for lookup of previously materialized objects
Ben Murdochda12d292016-06-02 14:46:10 +0100704 intptr_t stack_fp_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000705
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706 TranslatedState translated_state_;
707 struct ValueToMaterialize {
708 Address output_slot_address_;
709 TranslatedFrame::iterator value_;
710 };
711 std::vector<ValueToMaterialize> values_to_materialize_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000712
713#ifdef DEBUG
714 DisallowHeapAllocation* disallow_heap_allocation_;
715#endif // DEBUG
716
717 CodeTracer::Scope* trace_scope_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100718
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000719 static const int table_entry_size_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100720
721 friend class FrameDescription;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000722 friend class DeoptimizedFrameInfo;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100723};
724
725
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000726class RegisterValues {
727 public:
728 intptr_t GetRegister(unsigned n) const {
729#if DEBUG
730 // This convoluted DCHECK is needed to work around a gcc problem that
731 // improperly detects an array bounds overflow in optimized debug builds
732 // when using a plain DCHECK.
733 if (n >= arraysize(registers_)) {
734 DCHECK(false);
735 return 0;
736 }
737#endif
738 return registers_[n];
739 }
740
741 double GetDoubleRegister(unsigned n) const {
742 DCHECK(n < arraysize(double_registers_));
743 return double_registers_[n];
744 }
745
746 void SetRegister(unsigned n, intptr_t value) {
747 DCHECK(n < arraysize(registers_));
748 registers_[n] = value;
749 }
750
751 void SetDoubleRegister(unsigned n, double value) {
752 DCHECK(n < arraysize(double_registers_));
753 double_registers_[n] = value;
754 }
755
756 intptr_t registers_[Register::kNumRegisters];
757 double double_registers_[DoubleRegister::kMaxNumRegisters];
758};
759
760
Ben Murdochb0fe1622011-05-05 13:52:32 +0100761class FrameDescription {
762 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100763 explicit FrameDescription(uint32_t frame_size, int parameter_count = 0);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100764
765 void* operator new(size_t size, uint32_t frame_size) {
Steve Block44f0eee2011-05-26 01:26:41 +0100766 // Subtracts kPointerSize, as the member frame_content_ already supplies
767 // the first element of the area to store the frame.
768 return malloc(size + frame_size - kPointerSize);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100769 }
770
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000771 void operator delete(void* pointer, uint32_t frame_size) {
772 free(pointer);
773 }
774
Ben Murdochb0fe1622011-05-05 13:52:32 +0100775 void operator delete(void* description) {
776 free(description);
777 }
778
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000779 uint32_t GetFrameSize() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000780 DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000781 return static_cast<uint32_t>(frame_size_);
782 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100783
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100784 unsigned GetOffsetFromSlotIndex(int slot_index);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100785
786 intptr_t GetFrameSlot(unsigned offset) {
787 return *GetFrameSlotPointer(offset);
788 }
789
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000790 Address GetFramePointerAddress() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100791 int fp_offset = GetFrameSize() - parameter_count() * kPointerSize -
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000792 StandardFrameConstants::kCallerSPOffset;
793 return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100794 }
795
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000796 RegisterValues* GetRegisterValues() { return &register_values_; }
797
Ben Murdochb0fe1622011-05-05 13:52:32 +0100798 void SetFrameSlot(unsigned offset, intptr_t value) {
799 *GetFrameSlotPointer(offset) = value;
800 }
801
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000802 void SetCallerPc(unsigned offset, intptr_t value);
803
804 void SetCallerFp(unsigned offset, intptr_t value);
805
806 void SetCallerConstantPool(unsigned offset, intptr_t value);
807
Ben Murdochb0fe1622011-05-05 13:52:32 +0100808 intptr_t GetRegister(unsigned n) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000809 return register_values_.GetRegister(n);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100810 }
811
812 double GetDoubleRegister(unsigned n) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000813 return register_values_.GetDoubleRegister(n);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100814 }
815
816 void SetRegister(unsigned n, intptr_t value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000817 register_values_.SetRegister(n, value);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100818 }
819
820 void SetDoubleRegister(unsigned n, double value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000821 register_values_.SetDoubleRegister(n, value);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100822 }
823
824 intptr_t GetTop() const { return top_; }
825 void SetTop(intptr_t top) { top_ = top; }
826
827 intptr_t GetPc() const { return pc_; }
828 void SetPc(intptr_t pc) { pc_ = pc; }
829
830 intptr_t GetFp() const { return fp_; }
831 void SetFp(intptr_t fp) { fp_ = fp; }
832
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100833 intptr_t GetContext() const { return context_; }
834 void SetContext(intptr_t context) { context_ = context; }
835
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000836 intptr_t GetConstantPool() const { return constant_pool_; }
837 void SetConstantPool(intptr_t constant_pool) {
838 constant_pool_ = constant_pool;
839 }
840
Ben Murdochb0fe1622011-05-05 13:52:32 +0100841 Smi* GetState() const { return state_; }
842 void SetState(Smi* state) { state_ = state; }
843
844 void SetContinuation(intptr_t pc) { continuation_ = pc; }
845
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100846 StackFrame::Type GetFrameType() const { return type_; }
847 void SetFrameType(StackFrame::Type type) { type_ = type; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000848
Ben Murdoch097c5b22016-05-18 11:27:45 +0100849 // Argument count, including receiver.
850 int parameter_count() { return parameter_count_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000851
Ben Murdochb0fe1622011-05-05 13:52:32 +0100852 static int registers_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853 return OFFSET_OF(FrameDescription, register_values_.registers_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100854 }
855
856 static int double_registers_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000857 return OFFSET_OF(FrameDescription, register_values_.double_registers_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100858 }
859
860 static int frame_size_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000861 return offsetof(FrameDescription, frame_size_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100862 }
863
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000864 static int pc_offset() { return offsetof(FrameDescription, pc_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100865
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000866 static int state_offset() { return offsetof(FrameDescription, state_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100867
868 static int continuation_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000869 return offsetof(FrameDescription, continuation_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100870 }
871
872 static int frame_content_offset() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000873 return offsetof(FrameDescription, frame_content_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100874 }
875
876 private:
877 static const uint32_t kZapUint32 = 0xbeeddead;
878
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000879 // Frame_size_ must hold a uint32_t value. It is only a uintptr_t to
880 // keep the variable-size array frame_content_ of type intptr_t at
881 // the end of the structure aligned.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100882 uintptr_t frame_size_; // Number of bytes.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100883 int parameter_count_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000884 RegisterValues register_values_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100885 intptr_t top_;
886 intptr_t pc_;
887 intptr_t fp_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100888 intptr_t context_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000889 intptr_t constant_pool_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100890 StackFrame::Type type_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100891 Smi* state_;
892
893 // Continuation is the PC where the execution continues after
894 // deoptimizing.
895 intptr_t continuation_;
896
Steve Block44f0eee2011-05-26 01:26:41 +0100897 // This must be at the end of the object as the object is allocated larger
898 // than it's definition indicate to extend this array.
899 intptr_t frame_content_[1];
900
Ben Murdochb0fe1622011-05-05 13:52:32 +0100901 intptr_t* GetFrameSlotPointer(unsigned offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000902 DCHECK(offset < frame_size_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100903 return reinterpret_cast<intptr_t*>(
904 reinterpret_cast<Address>(this) + frame_content_offset() + offset);
905 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100906
907 int ComputeFixedSize();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100908};
909
910
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000911class DeoptimizerData {
912 public:
913 explicit DeoptimizerData(MemoryAllocator* allocator);
914 ~DeoptimizerData();
915
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000916 private:
917 MemoryAllocator* allocator_;
Ben Murdochda12d292016-06-02 14:46:10 +0100918 int deopt_entry_code_entries_[Deoptimizer::kLastBailoutType + 1];
919 MemoryChunk* deopt_entry_code_[Deoptimizer::kLastBailoutType + 1];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000920
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000921 Deoptimizer* current_;
922
923 friend class Deoptimizer;
924
925 DISALLOW_COPY_AND_ASSIGN(DeoptimizerData);
926};
927
928
Ben Murdochb0fe1622011-05-05 13:52:32 +0100929class TranslationBuffer BASE_EMBEDDED {
930 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000931 explicit TranslationBuffer(Zone* zone) : contents_(256, zone) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100932
933 int CurrentIndex() const { return contents_.length(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000934 void Add(int32_t value, Zone* zone);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100935
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000936 Handle<ByteArray> CreateByteArray(Factory* factory);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100937
938 private:
939 ZoneList<uint8_t> contents_;
940};
941
942
943class TranslationIterator BASE_EMBEDDED {
944 public:
945 TranslationIterator(ByteArray* buffer, int index)
946 : buffer_(buffer), index_(index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000947 DCHECK(index >= 0 && index < buffer->length());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100948 }
949
950 int32_t Next();
951
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000952 bool HasNext() const { return index_ < buffer_->length(); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100953
954 void Skip(int n) {
955 for (int i = 0; i < n; i++) Next();
956 }
957
958 private:
959 ByteArray* buffer_;
960 int index_;
961};
962
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000963#define TRANSLATION_OPCODE_LIST(V) \
964 V(BEGIN) \
965 V(JS_FRAME) \
966 V(INTERPRETED_FRAME) \
967 V(CONSTRUCT_STUB_FRAME) \
968 V(GETTER_STUB_FRAME) \
969 V(SETTER_STUB_FRAME) \
970 V(ARGUMENTS_ADAPTOR_FRAME) \
Ben Murdochda12d292016-06-02 14:46:10 +0100971 V(TAIL_CALLER_FRAME) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000972 V(COMPILED_STUB_FRAME) \
973 V(DUPLICATED_OBJECT) \
974 V(ARGUMENTS_OBJECT) \
975 V(CAPTURED_OBJECT) \
976 V(REGISTER) \
977 V(INT32_REGISTER) \
978 V(UINT32_REGISTER) \
979 V(BOOL_REGISTER) \
980 V(DOUBLE_REGISTER) \
981 V(STACK_SLOT) \
982 V(INT32_STACK_SLOT) \
983 V(UINT32_STACK_SLOT) \
984 V(BOOL_STACK_SLOT) \
985 V(DOUBLE_STACK_SLOT) \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100986 V(LITERAL)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000987
Ben Murdochb0fe1622011-05-05 13:52:32 +0100988class Translation BASE_EMBEDDED {
989 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000990#define DECLARE_TRANSLATION_OPCODE_ENUM(item) item,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100991 enum Opcode {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000992 TRANSLATION_OPCODE_LIST(DECLARE_TRANSLATION_OPCODE_ENUM)
993 LAST = LITERAL
Ben Murdochb0fe1622011-05-05 13:52:32 +0100994 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995#undef DECLARE_TRANSLATION_OPCODE_ENUM
Ben Murdochb0fe1622011-05-05 13:52:32 +0100996
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000997 Translation(TranslationBuffer* buffer, int frame_count, int jsframe_count,
998 Zone* zone)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100999 : buffer_(buffer),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001000 index_(buffer->CurrentIndex()),
1001 zone_(zone) {
1002 buffer_->Add(BEGIN, zone);
1003 buffer_->Add(frame_count, zone);
1004 buffer_->Add(jsframe_count, zone);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001005 }
1006
1007 int index() const { return index_; }
1008
1009 // Commands.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001010 void BeginJSFrame(BailoutId node_id, int literal_id, unsigned height);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011 void BeginInterpretedFrame(BailoutId bytecode_offset, int literal_id,
1012 unsigned height);
1013 void BeginCompiledStubFrame(int height);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001014 void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
Ben Murdochda12d292016-06-02 14:46:10 +01001015 void BeginTailCallerFrame(int literal_id);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001016 void BeginConstructStubFrame(int literal_id, unsigned height);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001017 void BeginGetterStubFrame(int literal_id);
1018 void BeginSetterStubFrame(int literal_id);
1019 void BeginArgumentsObject(int args_length);
1020 void BeginCapturedObject(int length);
1021 void DuplicateObject(int object_index);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001022 void StoreRegister(Register reg);
1023 void StoreInt32Register(Register reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001024 void StoreUint32Register(Register reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001025 void StoreBoolRegister(Register reg);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001026 void StoreDoubleRegister(DoubleRegister reg);
1027 void StoreStackSlot(int index);
1028 void StoreInt32StackSlot(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001029 void StoreUint32StackSlot(int index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001030 void StoreBoolStackSlot(int index);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001031 void StoreDoubleStackSlot(int index);
1032 void StoreLiteral(int literal_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001033 void StoreArgumentsObject(bool args_known, int args_index, int args_length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001034 void StoreJSFrameFunction();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001035
1036 Zone* zone() const { return zone_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001037
1038 static int NumberOfOperandsFor(Opcode opcode);
1039
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001040#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001041 static const char* StringFor(Opcode opcode);
1042#endif
1043
1044 private:
1045 TranslationBuffer* buffer_;
1046 int index_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001047 Zone* zone_;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001048};
1049
1050
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001051class MaterializedObjectStore {
1052 public:
1053 explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) {
1054 }
1055
1056 Handle<FixedArray> Get(Address fp);
1057 void Set(Address fp, Handle<FixedArray> materialized_objects);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001058 bool Remove(Address fp);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001059
1060 private:
1061 Isolate* isolate() { return isolate_; }
1062 Handle<FixedArray> GetStackEntries();
1063 Handle<FixedArray> EnsureStackEntries(int size);
1064
1065 int StackIdToIndex(Address fp);
1066
1067 Isolate* isolate_;
1068 List<Address> frame_fps_;
Ben Murdoch8b112d22011-06-08 16:22:53 +01001069};
1070
1071
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001072// Class used to represent an unoptimized frame when the debugger
1073// needs to inspect a frame that is part of an optimized frame. The
1074// internally used FrameDescription objects are not GC safe so for use
1075// by the debugger frame information is copied to an object of this type.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001076// Represents parameters in unadapted form so their number might mismatch
1077// formal parameter count.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001078class DeoptimizedFrameInfo : public Malloced {
1079 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001080 DeoptimizedFrameInfo(TranslatedState* state,
1081 TranslatedState::iterator frame_it, Isolate* isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001082
1083 // Return the number of incoming arguments.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001084 int parameters_count() { return static_cast<int>(parameters_.size()); }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001085
1086 // Return the height of the expression stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001087 int expression_count() { return static_cast<int>(expression_stack_.size()); }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001088
1089 // Get the frame function.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001090 Handle<JSFunction> GetFunction() { return function_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001091
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001092 // Get the frame context.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001093 Handle<Object> GetContext() { return context_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001094
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001095 // Check if this frame is preceded by construct stub frame. The bottom-most
1096 // inlined frame might still be called by an uninlined construct stub.
1097 bool HasConstructStub() {
1098 return has_construct_stub_;
1099 }
1100
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001101 // Get an incoming argument.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001102 Handle<Object> GetParameter(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001103 DCHECK(0 <= index && index < parameters_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001104 return parameters_[index];
1105 }
1106
1107 // Get an expression from the expression stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001108 Handle<Object> GetExpression(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001109 DCHECK(0 <= index && index < expression_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001110 return expression_stack_[index];
1111 }
1112
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001113 int GetSourcePosition() {
1114 return source_position_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001115 }
1116
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001117 private:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001118 // Set an incoming argument.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001119 void SetParameter(int index, Handle<Object> obj) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001120 DCHECK(0 <= index && index < parameters_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001121 parameters_[index] = obj;
1122 }
1123
1124 // Set an expression on the expression stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001125 void SetExpression(int index, Handle<Object> obj) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001126 DCHECK(0 <= index && index < expression_count());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001127 expression_stack_[index] = obj;
1128 }
1129
Ben Murdoch097c5b22016-05-18 11:27:45 +01001130 Handle<JSFunction> function_;
1131 Handle<Object> context_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001132 bool has_construct_stub_;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001133 std::vector<Handle<Object> > parameters_;
1134 std::vector<Handle<Object> > expression_stack_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001135 int source_position_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001136
1137 friend class Deoptimizer;
1138};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001139
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001140} // namespace internal
1141} // namespace v8
Ben Murdochb0fe1622011-05-05 13:52:32 +01001142
1143#endif // V8_DEOPTIMIZER_H_