blob: 4cf41a9f277cadcfd3d4a99f12ea9754d8411591 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2013 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/deoptimizer.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +01006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#include "src/accessors.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/ast/prettyprinter.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/codegen.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/disasm.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/frames-inl.h"
12#include "src/full-codegen/full-codegen.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/global-handles.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010014#include "src/interpreter/interpreter.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015#include "src/macro-assembler.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010016#include "src/tracing/trace-event.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017#include "src/v8.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010018
19
20namespace v8 {
21namespace internal {
22
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023static MemoryChunk* AllocateCodeChunk(MemoryAllocator* allocator) {
24 return allocator->AllocateChunk(Deoptimizer::GetMaxDeoptTableSize(),
25 base::OS::CommitPageSize(),
26#if defined(__native_client__)
27 // The Native Client port of V8 uses an interpreter,
28 // so code pages don't need PROT_EXEC.
29 NOT_EXECUTABLE,
30#else
31 EXECUTABLE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000032#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033 NULL);
34}
35
36
37DeoptimizerData::DeoptimizerData(MemoryAllocator* allocator)
38 : allocator_(allocator),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039 current_(NULL) {
Ben Murdochda12d292016-06-02 14:46:10 +010040 for (int i = 0; i <= Deoptimizer::kLastBailoutType; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041 deopt_entry_code_entries_[i] = -1;
42 deopt_entry_code_[i] = AllocateCodeChunk(allocator);
43 }
Steve Block44f0eee2011-05-26 01:26:41 +010044}
Ben Murdochb0fe1622011-05-05 13:52:32 +010045
46
Steve Block44f0eee2011-05-26 01:26:41 +010047DeoptimizerData::~DeoptimizerData() {
Ben Murdochda12d292016-06-02 14:46:10 +010048 for (int i = 0; i <= Deoptimizer::kLastBailoutType; ++i) {
Ben Murdochc5610432016-08-08 18:44:38 +010049 allocator_->Free<MemoryAllocator::kFull>(deopt_entry_code_[i]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050 deopt_entry_code_[i] = NULL;
Steve Block44f0eee2011-05-26 01:26:41 +010051 }
52}
53
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000054
Ben Murdochb8a8cc12014-11-26 15:28:44 +000055Code* Deoptimizer::FindDeoptimizingCode(Address addr) {
56 if (function_->IsHeapObject()) {
57 // Search all deoptimizing code in the native context of the function.
Ben Murdoch61f157c2016-09-16 13:49:30 +010058 Isolate* isolate = function_->GetIsolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000059 Context* native_context = function_->context()->native_context();
60 Object* element = native_context->DeoptimizedCodeListHead();
Ben Murdoch61f157c2016-09-16 13:49:30 +010061 while (!element->IsUndefined(isolate)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 Code* code = Code::cast(element);
63 CHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
64 if (code->contains(addr)) return code;
65 element = code->next_code_link();
66 }
67 }
68 return NULL;
69}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000070
71
Ben Murdoch3ef787d2012-04-12 10:51:47 +010072// We rely on this function not causing a GC. It is called from generated code
73// without having a real stack frame in place.
Ben Murdochb0fe1622011-05-05 13:52:32 +010074Deoptimizer* Deoptimizer::New(JSFunction* function,
75 BailoutType type,
76 unsigned bailout_id,
77 Address from,
Steve Block44f0eee2011-05-26 01:26:41 +010078 int fp_to_sp_delta,
79 Isolate* isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +010080 Deoptimizer* deoptimizer = new Deoptimizer(isolate,
81 function,
82 type,
83 bailout_id,
84 from,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000085 fp_to_sp_delta,
86 NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087 CHECK(isolate->deoptimizer_data()->current_ == NULL);
Steve Block44f0eee2011-05-26 01:26:41 +010088 isolate->deoptimizer_data()->current_ = deoptimizer;
Ben Murdochb0fe1622011-05-05 13:52:32 +010089 return deoptimizer;
90}
91
92
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093// No larger than 2K on all platforms
94static const int kDeoptTableMaxEpilogueCodeSize = 2 * KB;
95
96
97size_t Deoptimizer::GetMaxDeoptTableSize() {
98 int entries_size =
99 Deoptimizer::kMaxNumberOfEntries * Deoptimizer::table_entry_size_;
100 int commit_page_size = static_cast<int>(base::OS::CommitPageSize());
101 int page_count = ((kDeoptTableMaxEpilogueCodeSize + entries_size - 1) /
102 commit_page_size) + 1;
103 return static_cast<size_t>(commit_page_size * page_count);
104}
105
106
Steve Block44f0eee2011-05-26 01:26:41 +0100107Deoptimizer* Deoptimizer::Grab(Isolate* isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +0100108 Deoptimizer* result = isolate->deoptimizer_data()->current_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109 CHECK_NOT_NULL(result);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100110 result->DeleteFrameDescriptions();
Steve Block44f0eee2011-05-26 01:26:41 +0100111 isolate->deoptimizer_data()->current_ = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100112 return result;
113}
114
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100115
116int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) {
117 if (jsframe_index == 0) return 0;
118
119 int frame_index = 0;
120 while (jsframe_index >= 0) {
121 FrameDescription* frame = output_[frame_index];
122 if (frame->GetFrameType() == StackFrame::JAVA_SCRIPT) {
123 jsframe_index--;
124 }
125 frame_index++;
126 }
127
128 return frame_index - 1;
129}
130
131
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000132DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
133 JavaScriptFrame* frame,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100134 int jsframe_index,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000135 Isolate* isolate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000136 CHECK(frame->is_optimized());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000137
Ben Murdoch097c5b22016-05-18 11:27:45 +0100138 TranslatedState translated_values(frame);
139 translated_values.Prepare(false, frame->fp());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000140
Ben Murdoch097c5b22016-05-18 11:27:45 +0100141 TranslatedState::iterator frame_it = translated_values.end();
142 int counter = jsframe_index;
143 for (auto it = translated_values.begin(); it != translated_values.end();
144 it++) {
145 if (it->kind() == TranslatedFrame::kFunction ||
146 it->kind() == TranslatedFrame::kInterpretedFunction) {
147 if (counter == 0) {
148 frame_it = it;
149 break;
150 }
151 counter--;
152 }
153 }
154 CHECK(frame_it != translated_values.end());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000155
Ben Murdoch097c5b22016-05-18 11:27:45 +0100156 DeoptimizedFrameInfo* info =
157 new DeoptimizedFrameInfo(&translated_values, frame_it, isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000158
159 return info;
160}
161
162
163void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
164 Isolate* isolate) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000165 delete info;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000166}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167
Ben Murdochb0fe1622011-05-05 13:52:32 +0100168
169void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
170 int count,
171 BailoutType type) {
172 TableEntryGenerator generator(masm, type, count);
173 generator.Generate();
174}
175
176
Ben Murdochb0fe1622011-05-05 13:52:32 +0100177void Deoptimizer::VisitAllOptimizedFunctionsForContext(
178 Context* context, OptimizedFunctionVisitor* visitor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000179 DisallowHeapAllocation no_allocation;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100180
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181 CHECK(context->IsNativeContext());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100182
183 visitor->EnterContext(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184
185 // Visit the list of optimized functions, removing elements that
186 // no longer refer to optimized code.
187 JSFunction* prev = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100188 Object* element = context->OptimizedFunctionsListHead();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100189 Isolate* isolate = context->GetIsolate();
190 while (!element->IsUndefined(isolate)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191 JSFunction* function = JSFunction::cast(element);
192 Object* next = function->next_function_link();
193 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION ||
194 (visitor->VisitFunction(function),
195 function->code()->kind() != Code::OPTIMIZED_FUNCTION)) {
196 // The function no longer refers to optimized code, or the visitor
197 // changed the code to which it refers to no longer be optimized code.
198 // Remove the function from this list.
199 if (prev != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 prev->set_next_function_link(next, UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000201 } else {
202 context->SetOptimizedFunctionsListHead(next);
203 }
204 // The visitor should not alter the link directly.
205 CHECK_EQ(function->next_function_link(), next);
206 // Set the next function link to undefined to indicate it is no longer
207 // in the optimized functions list.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 function->set_next_function_link(context->GetHeap()->undefined_value(),
209 SKIP_WRITE_BARRIER);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210 } else {
211 // The visitor should not alter the link directly.
212 CHECK_EQ(function->next_function_link(), next);
213 // preserve this element.
214 prev = function;
215 }
216 element = next;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100217 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218
Ben Murdochb0fe1622011-05-05 13:52:32 +0100219 visitor->LeaveContext(context);
220}
221
222
Ben Murdochb0fe1622011-05-05 13:52:32 +0100223void Deoptimizer::VisitAllOptimizedFunctions(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000224 Isolate* isolate,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100225 OptimizedFunctionVisitor* visitor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226 DisallowHeapAllocation no_allocation;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100227
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228 // Run through the list of all native contexts.
229 Object* context = isolate->heap()->native_contexts_list();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100230 while (!context->IsUndefined(isolate)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 VisitAllOptimizedFunctionsForContext(Context::cast(context), visitor);
Ben Murdochc5610432016-08-08 18:44:38 +0100232 context = Context::cast(context)->next_context_link();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100233 }
234}
235
236
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237// Unlink functions referring to code marked for deoptimization, then move
238// marked code from the optimized code list to the deoptimized code list,
239// and patch code for lazy deopt.
240void Deoptimizer::DeoptimizeMarkedCodeForContext(Context* context) {
241 DisallowHeapAllocation no_allocation;
242
243 // A "closure" that unlinks optimized code that is going to be
244 // deoptimized from the functions that refer to it.
245 class SelectedCodeUnlinker: public OptimizedFunctionVisitor {
246 public:
247 virtual void EnterContext(Context* context) { } // Don't care.
248 virtual void LeaveContext(Context* context) { } // Don't care.
249 virtual void VisitFunction(JSFunction* function) {
250 Code* code = function->code();
251 if (!code->marked_for_deoptimization()) return;
252
253 // Unlink this function and evict from optimized code map.
254 SharedFunctionInfo* shared = function->shared();
255 function->set_code(shared->code());
256
257 if (FLAG_trace_deopt) {
258 CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
259 PrintF(scope.file(), "[deoptimizer unlinked: ");
260 function->PrintName(scope.file());
261 PrintF(scope.file(),
262 " / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
263 }
264 }
265 };
266
267 // Unlink all functions that refer to marked code.
268 SelectedCodeUnlinker unlinker;
269 VisitAllOptimizedFunctionsForContext(context, &unlinker);
270
271 Isolate* isolate = context->GetHeap()->isolate();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100272#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273 Code* topmost_optimized_code = NULL;
274 bool safe_to_deopt_topmost_optimized_code = false;
275 // Make sure all activations of optimized code can deopt at their current PC.
276 // The topmost optimized code has special handling because it cannot be
277 // deoptimized due to weak object dependency.
278 for (StackFrameIterator it(isolate, isolate->thread_local_top());
279 !it.done(); it.Advance()) {
280 StackFrame::Type type = it.frame()->type();
281 if (type == StackFrame::OPTIMIZED) {
282 Code* code = it.frame()->LookupCode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000283 JSFunction* function =
284 static_cast<OptimizedFrame*>(it.frame())->function();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 if (FLAG_trace_deopt) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286 CodeTracer::Scope scope(isolate->GetCodeTracer());
287 PrintF(scope.file(), "[deoptimizer found activation of function: ");
288 function->PrintName(scope.file());
289 PrintF(scope.file(),
290 " / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
291 }
292 SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc());
293 int deopt_index = safepoint.deoptimization_index();
294 // Turbofan deopt is checked when we are patching addresses on stack.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 bool turbofanned = code->is_turbofanned() &&
296 function->shared()->asm_function() &&
297 !FLAG_turbo_asm_deoptimization;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 bool safe_to_deopt =
299 deopt_index != Safepoint::kNoDeoptimizationIndex || turbofanned;
Ben Murdochc5610432016-08-08 18:44:38 +0100300 bool builtin = code->kind() == Code::BUILTIN;
301 CHECK(topmost_optimized_code == NULL || safe_to_deopt || turbofanned ||
302 builtin);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303 if (topmost_optimized_code == NULL) {
304 topmost_optimized_code = code;
305 safe_to_deopt_topmost_optimized_code = safe_to_deopt;
306 }
307 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100308 }
309#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310
311 // Move marked code from the optimized code list to the deoptimized
312 // code list, collecting them into a ZoneList.
Ben Murdochda12d292016-06-02 14:46:10 +0100313 Zone zone(isolate->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000314 ZoneList<Code*> codes(10, &zone);
315
316 // Walk over all optimized code objects in this native context.
317 Code* prev = NULL;
318 Object* element = context->OptimizedCodeListHead();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100319 while (!element->IsUndefined(isolate)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320 Code* code = Code::cast(element);
321 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
322 Object* next = code->next_code_link();
323
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324 if (code->marked_for_deoptimization()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000325 // Put the code into the list for later patching.
326 codes.Add(code, &zone);
327
328 if (prev != NULL) {
329 // Skip this code in the optimized code list.
330 prev->set_next_code_link(next);
331 } else {
332 // There was no previous node, the next node is the new head.
333 context->SetOptimizedCodeListHead(next);
334 }
335
336 // Move the code to the _deoptimized_ code list.
337 code->set_next_code_link(context->DeoptimizedCodeListHead());
338 context->SetDeoptimizedCodeListHead(code);
339 } else {
340 // Not marked; preserve this element.
341 prev = code;
342 }
343 element = next;
344 }
345
Ben Murdoch097c5b22016-05-18 11:27:45 +0100346 // We need a handle scope only because of the macro assembler,
347 // which is used in code patching in EnsureCodeForDeoptimizationEntry.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348 HandleScope scope(isolate);
349
350 // Now patch all the codes for deoptimization.
351 for (int i = 0; i < codes.length(); i++) {
352#ifdef DEBUG
353 if (codes[i] == topmost_optimized_code) {
354 DCHECK(safe_to_deopt_topmost_optimized_code);
355 }
356#endif
357 // It is finally time to die, code object.
358
359 // Remove the code from optimized code map.
360 DeoptimizationInputData* deopt_data =
361 DeoptimizationInputData::cast(codes[i]->deoptimization_data());
362 SharedFunctionInfo* shared =
363 SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo());
364 shared->EvictFromOptimizedCodeMap(codes[i], "deoptimized code");
365
366 // Do platform-specific patching to force any activations to lazy deopt.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000367 PatchCodeForDeoptimization(isolate, codes[i]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000368
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000369 // We might be in the middle of incremental marking with compaction.
370 // Tell collector to treat this code object in a special way and
371 // ignore all slots that might have been recorded on it.
372 isolate->heap()->mark_compact_collector()->InvalidateCode(codes[i]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000373 }
374}
375
376
377void Deoptimizer::DeoptimizeAll(Isolate* isolate) {
Ben Murdochc5610432016-08-08 18:44:38 +0100378 RuntimeCallTimerScope runtimeTimer(isolate,
379 &RuntimeCallStats::DeoptimizeCode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100380 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
381 TRACE_EVENT0("v8", "V8.DeoptimizeCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000382 if (FLAG_trace_deopt) {
383 CodeTracer::Scope scope(isolate->GetCodeTracer());
384 PrintF(scope.file(), "[deoptimize all code in all contexts]\n");
385 }
386 DisallowHeapAllocation no_allocation;
387 // For all contexts, mark all code, then deoptimize.
388 Object* context = isolate->heap()->native_contexts_list();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100389 while (!context->IsUndefined(isolate)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000390 Context* native_context = Context::cast(context);
391 MarkAllCodeForContext(native_context);
392 DeoptimizeMarkedCodeForContext(native_context);
Ben Murdochc5610432016-08-08 18:44:38 +0100393 context = native_context->next_context_link();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000394 }
395}
396
397
398void Deoptimizer::DeoptimizeMarkedCode(Isolate* isolate) {
Ben Murdochc5610432016-08-08 18:44:38 +0100399 RuntimeCallTimerScope runtimeTimer(isolate,
400 &RuntimeCallStats::DeoptimizeCode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100401 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
402 TRACE_EVENT0("v8", "V8.DeoptimizeCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000403 if (FLAG_trace_deopt) {
404 CodeTracer::Scope scope(isolate->GetCodeTracer());
405 PrintF(scope.file(), "[deoptimize marked code in all contexts]\n");
406 }
407 DisallowHeapAllocation no_allocation;
408 // For all contexts, deoptimize code already marked.
409 Object* context = isolate->heap()->native_contexts_list();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100410 while (!context->IsUndefined(isolate)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000411 Context* native_context = Context::cast(context);
412 DeoptimizeMarkedCodeForContext(native_context);
Ben Murdochc5610432016-08-08 18:44:38 +0100413 context = native_context->next_context_link();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000414 }
415}
416
417
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000418void Deoptimizer::MarkAllCodeForContext(Context* context) {
419 Object* element = context->OptimizedCodeListHead();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100420 Isolate* isolate = context->GetIsolate();
421 while (!element->IsUndefined(isolate)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422 Code* code = Code::cast(element);
423 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
424 code->set_marked_for_deoptimization(true);
425 element = code->next_code_link();
426 }
427}
428
429
430void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
Ben Murdochc5610432016-08-08 18:44:38 +0100431 Isolate* isolate = function->GetIsolate();
432 RuntimeCallTimerScope runtimeTimer(isolate,
433 &RuntimeCallStats::DeoptimizeCode);
434 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100435 TRACE_EVENT0("v8", "V8.DeoptimizeCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000436 Code* code = function->code();
437 if (code->kind() == Code::OPTIMIZED_FUNCTION) {
438 // Mark the code for deoptimization and unlink any functions that also
439 // refer to that code. The code cannot be shared across native contexts,
440 // so we only need to search one.
441 code->set_marked_for_deoptimization(true);
442 DeoptimizeMarkedCodeForContext(function->context()->native_context());
443 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100444}
445
446
Ben Murdoch8b112d22011-06-08 16:22:53 +0100447void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100448 deoptimizer->DoComputeOutputFrames();
449}
450
451
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000452bool Deoptimizer::TraceEnabledFor(BailoutType deopt_type,
453 StackFrame::Type frame_type) {
454 switch (deopt_type) {
455 case EAGER:
456 case SOFT:
457 case LAZY:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000458 return (frame_type == StackFrame::STUB)
459 ? FLAG_trace_stub_failures
460 : FLAG_trace_deopt;
461 }
462 FATAL("Unsupported deopt type");
463 return false;
464}
465
466
467const char* Deoptimizer::MessageFor(BailoutType type) {
468 switch (type) {
469 case EAGER: return "eager";
470 case SOFT: return "soft";
471 case LAZY: return "lazy";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000472 }
473 FATAL("Unsupported deopt type");
474 return NULL;
475}
476
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function,
478 BailoutType type, unsigned bailout_id, Address from,
479 int fp_to_sp_delta, Code* optimized_code)
Steve Block44f0eee2011-05-26 01:26:41 +0100480 : isolate_(isolate),
481 function_(function),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100482 bailout_id_(bailout_id),
483 bailout_type_(type),
484 from_(from),
485 fp_to_sp_delta_(fp_to_sp_delta),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100486 deoptimizing_throw_(false),
487 catch_handler_data_(-1),
488 catch_handler_pc_offset_(-1),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000489 input_(nullptr),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100490 output_count_(0),
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100491 jsframe_count_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000492 output_(nullptr),
Ben Murdochda12d292016-06-02 14:46:10 +0100493 caller_frame_top_(0),
494 caller_fp_(0),
495 caller_pc_(0),
496 caller_constant_pool_(0),
497 input_frame_context_(0),
498 stack_fp_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000499 trace_scope_(nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100500 if (isolate->deoptimizer_lazy_throw()) {
501 isolate->set_deoptimizer_lazy_throw(false);
502 deoptimizing_throw_ = true;
503 }
504
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000505 // For COMPILED_STUBs called from builtins, the function pointer is a SMI
506 // indicating an internal frame.
507 if (function->IsSmi()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000508 function = nullptr;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100509 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000510 DCHECK(from != nullptr);
511 if (function != nullptr && function->IsOptimized()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000512 function->shared()->increment_deopt_count();
513 if (bailout_type_ == Deoptimizer::SOFT) {
514 isolate->counters()->soft_deopts_executed()->Increment();
515 // Soft deopts shouldn't count against the overall re-optimization count
516 // that can eventually lead to disabling optimization for a function.
517 int opt_count = function->shared()->opt_count();
518 if (opt_count > 0) opt_count--;
519 function->shared()->set_opt_count(opt_count);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100520 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100521 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000522 compiled_code_ = FindOptimizedCode(function, optimized_code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523#if DEBUG
524 DCHECK(compiled_code_ != NULL);
525 if (type == EAGER || type == SOFT || type == LAZY) {
526 DCHECK(compiled_code_->kind() != Code::FUNCTION);
527 }
528#endif
529
530 StackFrame::Type frame_type = function == NULL
531 ? StackFrame::STUB
532 : StackFrame::JAVA_SCRIPT;
533 trace_scope_ = TraceEnabledFor(type, frame_type) ?
534 new CodeTracer::Scope(isolate->GetCodeTracer()) : NULL;
535#ifdef DEBUG
536 CHECK(AllowHeapAllocation::IsAllowed());
537 disallow_heap_allocation_ = new DisallowHeapAllocation();
538#endif // DEBUG
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000539 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
540 PROFILE(isolate_, CodeDeoptEvent(compiled_code_, from_, fp_to_sp_delta_));
541 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100542 unsigned size = ComputeInputFrameSize();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100543 int parameter_count =
544 function == nullptr
545 ? 0
546 : (function->shared()->internal_formal_parameter_count() + 1);
547 input_ = new (size) FrameDescription(size, parameter_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000548 input_->SetFrameType(frame_type);
549}
550
551
552Code* Deoptimizer::FindOptimizedCode(JSFunction* function,
553 Code* optimized_code) {
554 switch (bailout_type_) {
555 case Deoptimizer::SOFT:
556 case Deoptimizer::EAGER:
557 case Deoptimizer::LAZY: {
558 Code* compiled_code = FindDeoptimizingCode(from_);
559 return (compiled_code == NULL)
560 ? static_cast<Code*>(isolate_->FindCodeObject(from_))
561 : compiled_code;
562 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000563 }
564 FATAL("Could not find code for optimized function");
565 return NULL;
566}
567
568
569void Deoptimizer::PrintFunctionName() {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100570 if (function_ != nullptr && function_->IsJSFunction()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400571 function_->ShortPrint(trace_scope_->file());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000572 } else {
573 PrintF(trace_scope_->file(),
574 "%s", Code::Kind2String(compiled_code_->kind()));
575 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100576}
577
578
579Deoptimizer::~Deoptimizer() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000580 DCHECK(input_ == NULL && output_ == NULL);
581 DCHECK(disallow_heap_allocation_ == NULL);
582 delete trace_scope_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100583}
584
585
586void Deoptimizer::DeleteFrameDescriptions() {
587 delete input_;
588 for (int i = 0; i < output_count_; ++i) {
589 if (output_[i] != input_) delete output_[i];
590 }
591 delete[] output_;
592 input_ = NULL;
593 output_ = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000594#ifdef DEBUG
595 CHECK(!AllowHeapAllocation::IsAllowed());
596 CHECK(disallow_heap_allocation_ != NULL);
597 delete disallow_heap_allocation_;
598 disallow_heap_allocation_ = NULL;
599#endif // DEBUG
Ben Murdochb0fe1622011-05-05 13:52:32 +0100600}
601
602
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000603Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate,
604 int id,
605 BailoutType type,
606 GetEntryMode mode) {
607 CHECK_GE(id, 0);
608 if (id >= kMaxNumberOfEntries) return NULL;
609 if (mode == ENSURE_ENTRY_CODE) {
610 EnsureCodeForDeoptimizationEntry(isolate, type, id);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100611 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000612 CHECK_EQ(mode, CALCULATE_ENTRY_ADDRESS);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100613 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000614 DeoptimizerData* data = isolate->deoptimizer_data();
Ben Murdochda12d292016-06-02 14:46:10 +0100615 CHECK_LE(type, kLastBailoutType);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000616 MemoryChunk* base = data->deopt_entry_code_[type];
617 return base->area_start() + (id * table_entry_size_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100618}
619
620
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000621int Deoptimizer::GetDeoptimizationId(Isolate* isolate,
622 Address addr,
623 BailoutType type) {
624 DeoptimizerData* data = isolate->deoptimizer_data();
625 MemoryChunk* base = data->deopt_entry_code_[type];
626 Address start = base->area_start();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400627 if (addr < start ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000628 addr >= start + (kMaxNumberOfEntries * table_entry_size_)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100629 return kNotDeoptimizationEntry;
630 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000631 DCHECK_EQ(0,
632 static_cast<int>(addr - start) % table_entry_size_);
633 return static_cast<int>(addr - start) / table_entry_size_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100634}
635
636
Steve Block9fac8402011-05-12 15:51:54 +0100637int Deoptimizer::GetOutputInfo(DeoptimizationOutputData* data,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000638 BailoutId id,
Steve Block9fac8402011-05-12 15:51:54 +0100639 SharedFunctionInfo* shared) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100640 // TODO(kasperl): For now, we do a simple linear search for the PC
641 // offset associated with the given node id. This should probably be
642 // changed to a binary search.
643 int length = data->DeoptPoints();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100644 for (int i = 0; i < length; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000645 if (data->AstId(i) == id) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100646 return data->PcAndState(i)->value();
647 }
648 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000649 OFStream os(stderr);
650 os << "[couldn't find pc offset for node=" << id.ToInt() << "]\n"
651 << "[method: " << shared->DebugName()->ToCString().get() << "]\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400652 << "[source:\n" << SourceCodeOf(shared) << "\n]" << std::endl;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100653
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000654 shared->GetHeap()->isolate()->PushStackTraceAndDie(0xfefefefe, data, shared,
655 0xfefefeff);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000656 FATAL("unable to find pc offset during deoptimization");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100657 return -1;
658}
659
660
Steve Block44f0eee2011-05-26 01:26:41 +0100661int Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100662 int length = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000663 // Count all entries in the deoptimizing code list of every context.
664 Object* context = isolate->heap()->native_contexts_list();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100665 while (!context->IsUndefined(isolate)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000666 Context* native_context = Context::cast(context);
667 Object* element = native_context->DeoptimizedCodeListHead();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100668 while (!element->IsUndefined(isolate)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000669 Code* code = Code::cast(element);
670 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
671 length++;
672 element = code->next_code_link();
673 }
Ben Murdochc5610432016-08-08 18:44:38 +0100674 context = Context::cast(context)->next_context_link();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100675 }
676 return length;
677}
678
Ben Murdoch097c5b22016-05-18 11:27:45 +0100679namespace {
680
681int LookupCatchHandler(TranslatedFrame* translated_frame, int* data_out) {
682 switch (translated_frame->kind()) {
683 case TranslatedFrame::kFunction: {
684 BailoutId node_id = translated_frame->node_id();
685 JSFunction* function =
686 JSFunction::cast(translated_frame->begin()->GetRawValue());
687 Code* non_optimized_code = function->shared()->code();
688 FixedArray* raw_data = non_optimized_code->deoptimization_data();
689 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
690 unsigned pc_and_state =
691 Deoptimizer::GetOutputInfo(data, node_id, function->shared());
692 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
693 HandlerTable* table =
694 HandlerTable::cast(non_optimized_code->handler_table());
695 HandlerTable::CatchPrediction prediction;
696 return table->LookupRange(pc_offset, data_out, &prediction);
697 }
698 case TranslatedFrame::kInterpretedFunction: {
699 int bytecode_offset = translated_frame->node_id().ToInt();
700 JSFunction* function =
701 JSFunction::cast(translated_frame->begin()->GetRawValue());
702 BytecodeArray* bytecode = function->shared()->bytecode_array();
703 HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
704 HandlerTable::CatchPrediction prediction;
705 return table->LookupRange(bytecode_offset, data_out, &prediction);
706 }
707 default:
708 break;
709 }
710 return -1;
711}
712
713} // namespace
Ben Murdochb0fe1622011-05-05 13:52:32 +0100714
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100715// We rely on this function not causing a GC. It is called from generated code
716// without having a real stack frame in place.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100717void Deoptimizer::DoComputeOutputFrames() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000718 base::ElapsedTimer timer;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100719
720 // Determine basic deoptimization information. The optimized frame is
721 // described by the input data.
722 DeoptimizationInputData* input_data =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000723 DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
724
Ben Murdochda12d292016-06-02 14:46:10 +0100725 {
726 // Read caller's PC, caller's FP and caller's constant pool values
727 // from input frame. Compute caller's frame top address.
728
729 Register fp_reg = JavaScriptFrame::fp_register();
730 stack_fp_ = input_->GetRegister(fp_reg.code());
731
732 caller_frame_top_ = stack_fp_ + ComputeInputFrameAboveFpFixedSize();
733
734 Address fp_address = input_->GetFramePointerAddress();
735 caller_fp_ = Memory::intptr_at(fp_address);
736 caller_pc_ =
737 Memory::intptr_at(fp_address + CommonFrameConstants::kCallerPCOffset);
738 input_frame_context_ = Memory::intptr_at(
739 fp_address + CommonFrameConstants::kContextOrFrameTypeOffset);
740
741 if (FLAG_enable_embedded_constant_pool) {
742 caller_constant_pool_ = Memory::intptr_at(
743 fp_address + CommonFrameConstants::kConstantPoolOffset);
744 }
745 }
746
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000747 if (trace_scope_ != NULL) {
748 timer.Start();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400749 PrintF(trace_scope_->file(), "[deoptimizing (DEOPT %s): begin ",
750 MessageFor(bailout_type_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000751 PrintFunctionName();
752 PrintF(trace_scope_->file(),
Ben Murdochda12d292016-06-02 14:46:10 +0100753 " (opt #%d) @%d, FP to SP delta: %d, caller sp: 0x%08" V8PRIxPTR
754 "]\n",
755 input_data->OptimizationId()->value(), bailout_id_, fp_to_sp_delta_,
756 caller_frame_top_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000757 if (bailout_type_ == EAGER || bailout_type_ == SOFT ||
758 (compiled_code_->is_hydrogen_stub())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000759 compiled_code_->PrintDeoptLocation(trace_scope_->file(), from_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000760 }
761 }
762
763 BailoutId node_id = input_data->AstId(bailout_id_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100764 ByteArray* translations = input_data->TranslationByteArray();
765 unsigned translation_index =
766 input_data->TranslationIndex(bailout_id_)->value();
767
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000768 TranslationIterator state_iterator(translations, translation_index);
769 translated_state_.Init(
770 input_->GetFramePointerAddress(), &state_iterator,
771 input_data->LiteralArray(), input_->GetRegisterValues(),
772 trace_scope_ == nullptr ? nullptr : trace_scope_->file());
773
Ben Murdochb0fe1622011-05-05 13:52:32 +0100774 // Do the input frame to output frame(s) translation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000775 size_t count = translated_state_.frames().size();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100776 // If we are supposed to go to the catch handler, find the catching frame
777 // for the catch and make sure we only deoptimize upto that frame.
778 if (deoptimizing_throw_) {
779 size_t catch_handler_frame_index = count;
780 for (size_t i = count; i-- > 0;) {
781 catch_handler_pc_offset_ = LookupCatchHandler(
782 &(translated_state_.frames()[i]), &catch_handler_data_);
783 if (catch_handler_pc_offset_ >= 0) {
784 catch_handler_frame_index = i;
785 break;
786 }
787 }
788 CHECK_LT(catch_handler_frame_index, count);
789 count = catch_handler_frame_index + 1;
790 }
791
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000792 DCHECK(output_ == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100793 output_ = new FrameDescription*[count];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000794 for (size_t i = 0; i < count; ++i) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100795 output_[i] = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100796 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000797 output_count_ = static_cast<int>(count);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100798
799 // Translate each output frame.
Ben Murdochda12d292016-06-02 14:46:10 +0100800 int frame_index = 0; // output_frame_index
801 for (size_t i = 0; i < count; ++i, ++frame_index) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100802 // Read the ast node id, function, and frame height for this output frame.
Ben Murdochda12d292016-06-02 14:46:10 +0100803 TranslatedFrame* translated_frame = &(translated_state_.frames()[i]);
804 switch (translated_frame->kind()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000805 case TranslatedFrame::kFunction:
Ben Murdochda12d292016-06-02 14:46:10 +0100806 DoComputeJSFrame(translated_frame, frame_index,
807 deoptimizing_throw_ && i == count - 1);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100808 jsframe_count_++;
809 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000810 case TranslatedFrame::kInterpretedFunction:
Ben Murdochda12d292016-06-02 14:46:10 +0100811 DoComputeInterpretedFrame(translated_frame, frame_index,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100812 deoptimizing_throw_ && i == count - 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000813 jsframe_count_++;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100814 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000815 case TranslatedFrame::kArgumentsAdaptor:
Ben Murdochda12d292016-06-02 14:46:10 +0100816 DoComputeArgumentsAdaptorFrame(translated_frame, frame_index);
817 break;
818 case TranslatedFrame::kTailCallerFunction:
819 DoComputeTailCallerFrame(translated_frame, frame_index);
820 // Tail caller frame translations do not produce output frames.
821 frame_index--;
822 output_count_--;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100823 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000824 case TranslatedFrame::kConstructStub:
Ben Murdochda12d292016-06-02 14:46:10 +0100825 DoComputeConstructStubFrame(translated_frame, frame_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000826 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000827 case TranslatedFrame::kGetter:
Ben Murdochda12d292016-06-02 14:46:10 +0100828 DoComputeAccessorStubFrame(translated_frame, frame_index, false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000829 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000830 case TranslatedFrame::kSetter:
Ben Murdochda12d292016-06-02 14:46:10 +0100831 DoComputeAccessorStubFrame(translated_frame, frame_index, true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000832 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000833 case TranslatedFrame::kCompiledStub:
Ben Murdochda12d292016-06-02 14:46:10 +0100834 DoComputeCompiledStubFrame(translated_frame, frame_index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000835 break;
836 case TranslatedFrame::kInvalid:
837 FATAL("invalid frame");
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100838 break;
839 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100840 }
841
842 // Print some helpful diagnostic information.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000843 if (trace_scope_ != NULL) {
844 double ms = timer.Elapsed().InMillisecondsF();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100845 int index = output_count_ - 1; // Index of the topmost frame.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400846 PrintF(trace_scope_->file(), "[deoptimizing (%s): end ",
847 MessageFor(bailout_type_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000848 PrintFunctionName();
849 PrintF(trace_scope_->file(),
Ben Murdochda12d292016-06-02 14:46:10 +0100850 " @%d => node=%d, pc=0x%08" V8PRIxPTR ", caller sp=0x%08" V8PRIxPTR
851 ", state=%s, took %0.3f ms]\n",
852 bailout_id_, node_id.ToInt(), output_[index]->GetPc(),
Ben Murdochc5610432016-08-08 18:44:38 +0100853 caller_frame_top_, BailoutStateToString(static_cast<BailoutState>(
854 output_[index]->GetState()->value())),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100855 ms);
856 }
857}
858
Ben Murdochda12d292016-06-02 14:46:10 +0100859void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame,
860 int frame_index, bool goto_catch_handler) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100861 SharedFunctionInfo* shared = translated_frame->raw_shared_info();
862
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000863 TranslatedFrame::iterator value_iterator = translated_frame->begin();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100864 bool is_bottommost = (0 == frame_index);
865 bool is_topmost = (output_count_ - 1 == frame_index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000866 int input_index = 0;
867
868 BailoutId node_id = translated_frame->node_id();
869 unsigned height =
870 translated_frame->height() - 1; // Do not count the context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000871 unsigned height_in_bytes = height * kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100872 if (goto_catch_handler) {
873 // Take the stack height from the handler table.
874 height = catch_handler_data_;
875 // We also make space for the exception itself.
876 height_in_bytes = (height + 1) * kPointerSize;
877 CHECK(is_topmost);
878 }
879
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
881 value_iterator++;
882 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000883 if (trace_scope_ != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000884 PrintF(trace_scope_->file(), " translating frame ");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100885 base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
886 PrintF(trace_scope_->file(), "%s", name.get());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100887 PrintF(trace_scope_->file(), " => node=%d, height=%d%s\n", node_id.ToInt(),
888 height_in_bytes, goto_catch_handler ? " (throw)" : "");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000889 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100890
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891 // The 'fixed' part of the frame consists of the incoming parameters and
892 // the part described by JavaScriptFrameConstants.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100893 unsigned fixed_frame_size = ComputeJavascriptFixedSize(shared);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000894 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
895
896 // Allocate and store the output frame description.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100897 int parameter_count = shared->internal_formal_parameter_count() + 1;
898 FrameDescription* output_frame = new (output_frame_size)
899 FrameDescription(output_frame_size, parameter_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000900 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
901
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000902 CHECK(frame_index >= 0 && frame_index < output_count_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000903 CHECK_NULL(output_[frame_index]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000904 output_[frame_index] = output_frame;
905
Ben Murdochda12d292016-06-02 14:46:10 +0100906 // The top address of the frame is computed from the previous frame's top and
907 // this frame's size.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000908 intptr_t top_address;
909 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +0100910 top_address = caller_frame_top_ - output_frame_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000911 } else {
912 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
913 }
914 output_frame->SetTop(top_address);
915
916 // Compute the incoming parameter translation.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000917 unsigned output_offset = output_frame_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000918 for (int i = 0; i < parameter_count; ++i) {
919 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000920 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
921 output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000922 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923
924 // There are no translation commands for the caller's pc and fp, the
925 // context, and the function. Synthesize their values and set them up
926 // explicitly.
927 //
928 // The caller's pc for the bottommost output frame is the same as in the
929 // input frame. For all subsequent output frames, it can be read from the
930 // previous one. This frame's pc can be computed from the non-optimized
931 // function code and AST id of the bailout.
932 output_offset -= kPCOnStackSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000933 intptr_t value;
934 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +0100935 value = caller_pc_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000936 } else {
937 value = output_[frame_index - 1]->GetPc();
938 }
939 output_frame->SetCallerPc(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000940 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000941
942 // The caller's frame pointer for the bottommost output frame is the same
943 // as in the input frame. For all subsequent output frames, it can be
944 // read from the previous one. Also compute and set this frame's frame
945 // pointer.
946 output_offset -= kFPOnStackSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000947 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +0100948 value = caller_fp_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000949 } else {
950 value = output_[frame_index - 1]->GetFp();
951 }
952 output_frame->SetCallerFp(output_offset, value);
953 intptr_t fp_value = top_address + output_offset;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000954 output_frame->SetFp(fp_value);
Ben Murdochda12d292016-06-02 14:46:10 +0100955 if (is_topmost) {
956 Register fp_reg = JavaScriptFrame::fp_register();
957 output_frame->SetRegister(fp_reg.code(), fp_value);
958 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000959 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000960
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000961 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000962 // For the bottommost output frame the constant pool pointer can be gotten
963 // from the input frame. For subsequent output frames, it can be read from
964 // the previous frame.
965 output_offset -= kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000966 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +0100967 value = caller_constant_pool_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000968 } else {
969 value = output_[frame_index - 1]->GetConstantPool();
970 }
971 output_frame->SetCallerConstantPool(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000972 DebugPrintOutputSlot(value, frame_index, output_offset,
973 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000974 }
975
976 // For the bottommost output frame the context can be gotten from the input
977 // frame. For all subsequent output frames it can be gotten from the function
978 // so long as we don't inline functions that need local contexts.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000979 output_offset -= kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100980
981 TranslatedFrame::iterator context_pos = value_iterator;
982 int context_input_index = input_index;
983 // When deoptimizing into a catch block, we need to take the context
984 // from just above the top of the operand stack (we push the context
985 // at the entry of the try block).
986 if (goto_catch_handler) {
987 for (unsigned i = 0; i < height + 1; ++i) {
988 context_pos++;
989 context_input_index++;
990 }
991 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000992 // Read the context from the translations.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100993 Object* context = context_pos->GetRawValue();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100994 if (context->IsUndefined(isolate_)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995 // If the context was optimized away, just use the context from
996 // the activation. This should only apply to Crankshaft code.
997 CHECK(!compiled_code_->is_turbofanned());
Ben Murdochda12d292016-06-02 14:46:10 +0100998 context = is_bottommost ? reinterpret_cast<Object*>(input_frame_context_)
999 : function->context();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001000 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001 value = reinterpret_cast<intptr_t>(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001002 output_frame->SetContext(value);
Ben Murdochda12d292016-06-02 14:46:10 +01001003 if (is_topmost) {
1004 Register context_reg = JavaScriptFrame::context_register();
1005 output_frame->SetRegister(context_reg.code(), value);
1006 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001007 WriteValueToOutput(context, context_input_index, frame_index, output_offset,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001008 "context ");
1009 if (context == isolate_->heap()->arguments_marker()) {
1010 Address output_address =
1011 reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
1012 output_offset;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001013 values_to_materialize_.push_back({output_address, context_pos});
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001014 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001015 value_iterator++;
1016 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001017
1018 // The function was mentioned explicitly in the BEGIN_FRAME.
1019 output_offset -= kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001020 value = reinterpret_cast<intptr_t>(function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001021 WriteValueToOutput(function, 0, frame_index, output_offset, "function ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001022
1023 // Translate the rest of the frame.
1024 for (unsigned i = 0; i < height; ++i) {
1025 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001026 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1027 output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001028 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001029 if (goto_catch_handler) {
1030 // Write out the exception for the catch handler.
1031 output_offset -= kPointerSize;
1032 Object* exception_obj = reinterpret_cast<Object*>(
1033 input_->GetRegister(FullCodeGenerator::result_register().code()));
1034 WriteValueToOutput(exception_obj, input_index, frame_index, output_offset,
1035 "exception ");
1036 input_index++;
1037 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001038 CHECK_EQ(0u, output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001039
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001040 // Update constant pool.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001041 Code* non_optimized_code = shared->code();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001042 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001043 intptr_t constant_pool_value =
1044 reinterpret_cast<intptr_t>(non_optimized_code->constant_pool());
1045 output_frame->SetConstantPool(constant_pool_value);
1046 if (is_topmost) {
1047 Register constant_pool_reg =
1048 JavaScriptFrame::constant_pool_pointer_register();
1049 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
1050 }
1051 }
1052
Ben Murdoch097c5b22016-05-18 11:27:45 +01001053 // Compute this frame's PC, state, and continuation.
1054 FixedArray* raw_data = non_optimized_code->deoptimization_data();
1055 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
1056 Address start = non_optimized_code->instruction_start();
1057 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared());
1058 unsigned pc_offset = goto_catch_handler
1059 ? catch_handler_pc_offset_
1060 : FullCodeGenerator::PcField::decode(pc_and_state);
1061 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset);
1062 output_frame->SetPc(pc_value);
1063
1064 // If we are going to the catch handler, then the exception lives in
1065 // the accumulator.
Ben Murdochc5610432016-08-08 18:44:38 +01001066 BailoutState state =
1067 goto_catch_handler
1068 ? BailoutState::TOS_REGISTER
1069 : FullCodeGenerator::BailoutStateField::decode(pc_and_state);
1070 output_frame->SetState(Smi::FromInt(static_cast<int>(state)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001071
1072 // Set the continuation for the topmost frame.
Ben Murdochda12d292016-06-02 14:46:10 +01001073 if (is_topmost) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001074 Builtins* builtins = isolate_->builtins();
1075 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
1076 if (bailout_type_ == LAZY) {
1077 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
1078 } else if (bailout_type_ == SOFT) {
1079 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized);
1080 } else {
1081 CHECK_EQ(bailout_type_, EAGER);
1082 }
1083 output_frame->SetContinuation(
1084 reinterpret_cast<intptr_t>(continuation->entry()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001085 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001086}
1087
Ben Murdochda12d292016-06-02 14:46:10 +01001088void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
1089 int frame_index,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001090 bool goto_catch_handler) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001091 SharedFunctionInfo* shared = translated_frame->raw_shared_info();
1092
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001093 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1094 int input_index = 0;
1095
Ben Murdoch097c5b22016-05-18 11:27:45 +01001096 int bytecode_offset = translated_frame->node_id().ToInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001097 unsigned height = translated_frame->height();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001098 unsigned height_in_bytes = height * kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001099 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
1100 value_iterator++;
1101 input_index++;
1102 if (trace_scope_ != NULL) {
1103 PrintF(trace_scope_->file(), " translating interpreted frame ");
Ben Murdoch097c5b22016-05-18 11:27:45 +01001104 base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
1105 PrintF(trace_scope_->file(), "%s", name.get());
1106 PrintF(trace_scope_->file(), " => bytecode_offset=%d, height=%d%s\n",
1107 bytecode_offset, height_in_bytes,
1108 goto_catch_handler ? " (throw)" : "");
1109 }
1110 if (goto_catch_handler) {
1111 bytecode_offset = catch_handler_pc_offset_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001112 }
1113
1114 // The 'fixed' part of the frame consists of the incoming parameters and
1115 // the part described by InterpreterFrameConstants.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001116 unsigned fixed_frame_size = ComputeInterpretedFixedSize(shared);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001117 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1118
1119 // Allocate and store the output frame description.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001120 int parameter_count = shared->internal_formal_parameter_count() + 1;
1121 FrameDescription* output_frame = new (output_frame_size)
1122 FrameDescription(output_frame_size, parameter_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001123 output_frame->SetFrameType(StackFrame::INTERPRETED);
1124
1125 bool is_bottommost = (0 == frame_index);
1126 bool is_topmost = (output_count_ - 1 == frame_index);
1127 CHECK(frame_index >= 0 && frame_index < output_count_);
1128 CHECK_NULL(output_[frame_index]);
1129 output_[frame_index] = output_frame;
1130
Ben Murdochda12d292016-06-02 14:46:10 +01001131 // The top address of the frame is computed from the previous frame's top and
1132 // this frame's size.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001133 intptr_t top_address;
1134 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +01001135 top_address = caller_frame_top_ - output_frame_size;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001136 } else {
1137 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1138 }
1139 output_frame->SetTop(top_address);
1140
1141 // Compute the incoming parameter translation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001142 unsigned output_offset = output_frame_size;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001143 for (int i = 0; i < parameter_count; ++i) {
1144 output_offset -= kPointerSize;
1145 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1146 output_offset);
1147 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001148
1149 // There are no translation commands for the caller's pc and fp, the
1150 // context, the function, new.target and the bytecode offset. Synthesize
1151 // their values and set them up
1152 // explicitly.
1153 //
1154 // The caller's pc for the bottommost output frame is the same as in the
1155 // input frame. For all subsequent output frames, it can be read from the
1156 // previous one. This frame's pc can be computed from the non-optimized
1157 // function code and AST id of the bailout.
1158 output_offset -= kPCOnStackSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001159 intptr_t value;
1160 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +01001161 value = caller_pc_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001162 } else {
1163 value = output_[frame_index - 1]->GetPc();
1164 }
1165 output_frame->SetCallerPc(output_offset, value);
1166 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's pc\n");
1167
1168 // The caller's frame pointer for the bottommost output frame is the same
1169 // as in the input frame. For all subsequent output frames, it can be
1170 // read from the previous one. Also compute and set this frame's frame
1171 // pointer.
1172 output_offset -= kFPOnStackSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001173 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +01001174 value = caller_fp_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001175 } else {
1176 value = output_[frame_index - 1]->GetFp();
1177 }
1178 output_frame->SetCallerFp(output_offset, value);
1179 intptr_t fp_value = top_address + output_offset;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001180 output_frame->SetFp(fp_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001181 if (is_topmost) {
1182 Register fp_reg = InterpretedFrame::fp_register();
1183 output_frame->SetRegister(fp_reg.code(), fp_value);
1184 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001185 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001186
1187 if (FLAG_enable_embedded_constant_pool) {
1188 // For the bottommost output frame the constant pool pointer can be gotten
1189 // from the input frame. For subsequent output frames, it can be read from
1190 // the previous frame.
1191 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001192 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +01001193 value = caller_constant_pool_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001194 } else {
1195 value = output_[frame_index - 1]->GetConstantPool();
1196 }
1197 output_frame->SetCallerConstantPool(output_offset, value);
1198 DebugPrintOutputSlot(value, frame_index, output_offset,
1199 "caller's constant_pool\n");
1200 }
1201
1202 // For the bottommost output frame the context can be gotten from the input
1203 // frame. For all subsequent output frames it can be gotten from the function
1204 // so long as we don't inline functions that need local contexts.
1205 Register context_reg = InterpretedFrame::context_register();
1206 output_offset -= kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001207
1208 // When deoptimizing into a catch block, we need to take the context
1209 // from a register that was specified in the handler table.
1210 TranslatedFrame::iterator context_pos = value_iterator;
1211 int context_input_index = input_index;
1212 if (goto_catch_handler) {
1213 // Skip to the translated value of the register specified
1214 // in the handler table.
1215 for (int i = 0; i < catch_handler_data_ + 1; ++i) {
1216 context_pos++;
1217 context_input_index++;
1218 }
1219 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001220 // Read the context from the translations.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001221 Object* context = context_pos->GetRawValue();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001222 // The context should not be a placeholder for a materialized object.
1223 CHECK(context != isolate_->heap()->arguments_marker());
1224 value = reinterpret_cast<intptr_t>(context);
1225 output_frame->SetContext(value);
1226 if (is_topmost) output_frame->SetRegister(context_reg.code(), value);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001227 WriteValueToOutput(context, context_input_index, frame_index, output_offset,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001228 "context ");
1229 value_iterator++;
1230 input_index++;
1231
1232 // The function was mentioned explicitly in the BEGIN_FRAME.
1233 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 value = reinterpret_cast<intptr_t>(function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001235 WriteValueToOutput(function, 0, frame_index, output_offset, "function ");
1236
Ben Murdoch097c5b22016-05-18 11:27:45 +01001237 // The new.target slot is only used during function activiation which is
1238 // before the first deopt point, so should never be needed. Just set it to
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001239 // undefined.
1240 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001241 Object* new_target = isolate_->heap()->undefined_value();
1242 WriteValueToOutput(new_target, 0, frame_index, output_offset, "new_target ");
1243
Ben Murdoch097c5b22016-05-18 11:27:45 +01001244 // Set the bytecode array pointer.
1245 output_offset -= kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001246 Object* bytecode_array = shared->bytecode_array();
1247 WriteValueToOutput(bytecode_array, 0, frame_index, output_offset,
1248 "bytecode array ");
1249
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001250 // The bytecode offset was mentioned explicitly in the BEGIN_FRAME.
1251 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001252 int raw_bytecode_offset =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001253 BytecodeArray::kHeaderSize - kHeapObjectTag + bytecode_offset;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001254 Smi* smi_bytecode_offset = Smi::FromInt(raw_bytecode_offset);
1255 WriteValueToOutput(smi_bytecode_offset, 0, frame_index, output_offset,
1256 "bytecode offset ");
1257
1258 // Translate the rest of the interpreter registers in the frame.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001259 for (unsigned i = 0; i < height - 1; ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001260 output_offset -= kPointerSize;
1261 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1262 output_offset);
1263 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001264
1265 // Put the accumulator on the stack. It will be popped by the
1266 // InterpreterNotifyDeopt builtin (possibly after materialization).
1267 output_offset -= kPointerSize;
1268 if (goto_catch_handler) {
1269 // If we are lazy deopting to a catch handler, we set the accumulator to
1270 // the exception (which lives in the result register).
1271 intptr_t accumulator_value =
1272 input_->GetRegister(FullCodeGenerator::result_register().code());
1273 WriteValueToOutput(reinterpret_cast<Object*>(accumulator_value), 0,
1274 frame_index, output_offset, "accumulator ");
1275 value_iterator++;
1276 } else {
1277 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1278 output_offset);
1279 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001280 CHECK_EQ(0u, output_offset);
1281
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001282 Builtins* builtins = isolate_->builtins();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001283 Code* dispatch_builtin =
1284 builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
1285 output_frame->SetPc(reinterpret_cast<intptr_t>(dispatch_builtin->entry()));
Ben Murdochc5610432016-08-08 18:44:38 +01001286 // Restore accumulator (TOS) register.
1287 output_frame->SetState(
1288 Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001289
1290 // Update constant pool.
1291 if (FLAG_enable_embedded_constant_pool) {
1292 intptr_t constant_pool_value =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001293 reinterpret_cast<intptr_t>(dispatch_builtin->constant_pool());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001294 output_frame->SetConstantPool(constant_pool_value);
1295 if (is_topmost) {
1296 Register constant_pool_reg =
1297 InterpretedFrame::constant_pool_pointer_register();
1298 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
1299 }
1300 }
1301
1302 // Set the continuation for the topmost frame.
Ben Murdochda12d292016-06-02 14:46:10 +01001303 if (is_topmost) {
Ben Murdochc5610432016-08-08 18:44:38 +01001304 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001305 if (bailout_type_ == LAZY) {
Ben Murdochc5610432016-08-08 18:44:38 +01001306 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001307 } else if (bailout_type_ == SOFT) {
Ben Murdochc5610432016-08-08 18:44:38 +01001308 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001309 } else {
1310 CHECK_EQ(bailout_type_, EAGER);
1311 }
1312 output_frame->SetContinuation(
1313 reinterpret_cast<intptr_t>(continuation->entry()));
1314 }
1315}
1316
Ben Murdochda12d292016-06-02 14:46:10 +01001317void Deoptimizer::DoComputeArgumentsAdaptorFrame(
1318 TranslatedFrame* translated_frame, int frame_index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001319 TranslatedFrame::iterator value_iterator = translated_frame->begin();
Ben Murdochda12d292016-06-02 14:46:10 +01001320 bool is_bottommost = (0 == frame_index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001321 int input_index = 0;
1322
1323 unsigned height = translated_frame->height();
1324 unsigned height_in_bytes = height * kPointerSize;
1325 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
1326 value_iterator++;
1327 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001328 if (trace_scope_ != NULL) {
1329 PrintF(trace_scope_->file(),
1330 " translating arguments adaptor => height=%d\n", height_in_bytes);
1331 }
1332
Ben Murdochda12d292016-06-02 14:46:10 +01001333 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFixedFrameSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1335
1336 // Allocate and store the output frame description.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001337 int parameter_count = height;
1338 FrameDescription* output_frame = new (output_frame_size)
1339 FrameDescription(output_frame_size, parameter_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001340 output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);
1341
Ben Murdochda12d292016-06-02 14:46:10 +01001342 // Arguments adaptor can not be topmost.
1343 CHECK(frame_index < output_count_ - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001344 CHECK(output_[frame_index] == NULL);
1345 output_[frame_index] = output_frame;
1346
Ben Murdochda12d292016-06-02 14:46:10 +01001347 // The top address of the frame is computed from the previous frame's top and
1348 // this frame's size.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001349 intptr_t top_address;
Ben Murdochda12d292016-06-02 14:46:10 +01001350 if (is_bottommost) {
1351 top_address = caller_frame_top_ - output_frame_size;
1352 } else {
1353 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1354 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001355 output_frame->SetTop(top_address);
1356
1357 // Compute the incoming parameter translation.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001358 unsigned output_offset = output_frame_size;
1359 for (int i = 0; i < parameter_count; ++i) {
1360 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001361 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1362 output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001363 }
1364
1365 // Read caller's PC from the previous frame.
1366 output_offset -= kPCOnStackSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001367 intptr_t value;
1368 if (is_bottommost) {
1369 value = caller_pc_;
1370 } else {
1371 value = output_[frame_index - 1]->GetPc();
1372 }
1373 output_frame->SetCallerPc(output_offset, value);
1374 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001375
1376 // Read caller's FP from the previous frame, and set this frame's FP.
1377 output_offset -= kFPOnStackSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001378 if (is_bottommost) {
1379 value = caller_fp_;
1380 } else {
1381 value = output_[frame_index - 1]->GetFp();
1382 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001383 output_frame->SetCallerFp(output_offset, value);
1384 intptr_t fp_value = top_address + output_offset;
1385 output_frame->SetFp(fp_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001386 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001387
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001388 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001389 // Read the caller's constant pool from the previous frame.
1390 output_offset -= kPointerSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001391 if (is_bottommost) {
1392 value = caller_constant_pool_;
1393 } else {
1394 value = output_[frame_index - 1]->GetConstantPool();
1395 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001396 output_frame->SetCallerConstantPool(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001397 DebugPrintOutputSlot(value, frame_index, output_offset,
1398 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001399 }
1400
1401 // A marker value is used in place of the context.
1402 output_offset -= kPointerSize;
1403 intptr_t context = reinterpret_cast<intptr_t>(
1404 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1405 output_frame->SetFrameSlot(output_offset, context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001406 DebugPrintOutputSlot(context, frame_index, output_offset,
1407 "context (adaptor sentinel)\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001408
1409 // The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
1410 output_offset -= kPointerSize;
1411 value = reinterpret_cast<intptr_t>(function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001412 WriteValueToOutput(function, 0, frame_index, output_offset, "function ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001413
1414 // Number of incoming arguments.
1415 output_offset -= kPointerSize;
1416 value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
1417 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001418 DebugPrintOutputSlot(value, frame_index, output_offset, "argc ");
1419 if (trace_scope_ != nullptr) {
1420 PrintF(trace_scope_->file(), "(%d)\n", height - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001421 }
1422
1423 DCHECK(0 == output_offset);
1424
1425 Builtins* builtins = isolate_->builtins();
1426 Code* adaptor_trampoline =
1427 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
1428 intptr_t pc_value = reinterpret_cast<intptr_t>(
1429 adaptor_trampoline->instruction_start() +
1430 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
1431 output_frame->SetPc(pc_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001432 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001433 intptr_t constant_pool_value =
1434 reinterpret_cast<intptr_t>(adaptor_trampoline->constant_pool());
1435 output_frame->SetConstantPool(constant_pool_value);
1436 }
1437}
1438
Ben Murdochda12d292016-06-02 14:46:10 +01001439void Deoptimizer::DoComputeTailCallerFrame(TranslatedFrame* translated_frame,
1440 int frame_index) {
1441 SharedFunctionInfo* shared = translated_frame->raw_shared_info();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001442
Ben Murdochda12d292016-06-02 14:46:10 +01001443 bool is_bottommost = (0 == frame_index);
1444 // Tail caller frame can't be topmost.
1445 CHECK_NE(output_count_ - 1, frame_index);
1446
1447 if (trace_scope_ != NULL) {
1448 PrintF(trace_scope_->file(), " translating tail caller frame ");
1449 base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
1450 PrintF(trace_scope_->file(), "%s\n", name.get());
1451 }
1452
1453 if (!is_bottommost) return;
1454
1455 // Drop arguments adaptor frame below current frame if it exsits.
1456 Address fp_address = input_->GetFramePointerAddress();
1457 Address adaptor_fp_address =
1458 Memory::Address_at(fp_address + CommonFrameConstants::kCallerFPOffset);
1459
1460 if (Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR) !=
1461 Memory::Object_at(adaptor_fp_address +
1462 CommonFrameConstants::kContextOrFrameTypeOffset)) {
1463 return;
1464 }
1465
1466 int caller_params_count =
1467 Smi::cast(
1468 Memory::Object_at(adaptor_fp_address +
1469 ArgumentsAdaptorFrameConstants::kLengthOffset))
1470 ->value();
1471
1472 int callee_params_count =
1473 function_->shared()->internal_formal_parameter_count();
1474
1475 // Both caller and callee parameters count do not include receiver.
1476 int offset = (caller_params_count - callee_params_count) * kPointerSize;
1477 intptr_t new_stack_fp =
1478 reinterpret_cast<intptr_t>(adaptor_fp_address) + offset;
1479
1480 intptr_t new_caller_frame_top = new_stack_fp +
1481 (callee_params_count + 1) * kPointerSize +
1482 CommonFrameConstants::kFixedFrameSizeAboveFp;
1483
1484 intptr_t adaptor_caller_pc = Memory::intptr_at(
1485 adaptor_fp_address + CommonFrameConstants::kCallerPCOffset);
1486 intptr_t adaptor_caller_fp = Memory::intptr_at(
1487 adaptor_fp_address + CommonFrameConstants::kCallerFPOffset);
1488
1489 if (trace_scope_ != NULL) {
1490 PrintF(trace_scope_->file(),
1491 " dropping caller arguments adaptor frame: offset=%d, "
1492 "fp: 0x%08" V8PRIxPTR " -> 0x%08" V8PRIxPTR
1493 ", "
1494 "caller sp: 0x%08" V8PRIxPTR " -> 0x%08" V8PRIxPTR "\n",
1495 offset, stack_fp_, new_stack_fp, caller_frame_top_,
1496 new_caller_frame_top);
1497 }
1498 caller_frame_top_ = new_caller_frame_top;
1499 caller_fp_ = adaptor_caller_fp;
1500 caller_pc_ = adaptor_caller_pc;
1501}
1502
1503void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
1504 int frame_index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001505 TranslatedFrame::iterator value_iterator = translated_frame->begin();
Ben Murdochda12d292016-06-02 14:46:10 +01001506 bool is_topmost = (output_count_ - 1 == frame_index);
1507 // The construct frame could become topmost only if we inlined a constructor
1508 // call which does a tail call (otherwise the tail callee's frame would be
1509 // the topmost one). So it could only be the LAZY case.
1510 CHECK(!is_topmost || bailout_type_ == LAZY);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001511 int input_index = 0;
1512
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001513 Builtins* builtins = isolate_->builtins();
1514 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001515 unsigned height = translated_frame->height();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001516 unsigned height_in_bytes = height * kPointerSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001517
1518 // If the construct frame appears to be topmost we should ensure that the
1519 // value of result register is preserved during continuation execution.
1520 // We do this here by "pushing" the result of the constructor function to the
1521 // top of the reconstructed stack and then using the
Ben Murdochc5610432016-08-08 18:44:38 +01001522 // BailoutState::TOS_REGISTER machinery.
Ben Murdochda12d292016-06-02 14:46:10 +01001523 if (is_topmost) {
1524 height_in_bytes += kPointerSize;
1525 }
1526
Ben Murdoch097c5b22016-05-18 11:27:45 +01001527 // Skip function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001528 value_iterator++;
1529 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001530 if (trace_scope_ != NULL) {
1531 PrintF(trace_scope_->file(),
1532 " translating construct stub => height=%d\n", height_in_bytes);
1533 }
1534
Ben Murdochda12d292016-06-02 14:46:10 +01001535 unsigned fixed_frame_size = ConstructFrameConstants::kFixedFrameSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001536 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1537
1538 // Allocate and store the output frame description.
1539 FrameDescription* output_frame =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001540 new (output_frame_size) FrameDescription(output_frame_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001541 output_frame->SetFrameType(StackFrame::CONSTRUCT);
1542
Ben Murdochda12d292016-06-02 14:46:10 +01001543 // Construct stub can not be topmost.
1544 DCHECK(frame_index > 0 && frame_index < output_count_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001545 DCHECK(output_[frame_index] == NULL);
1546 output_[frame_index] = output_frame;
1547
Ben Murdochda12d292016-06-02 14:46:10 +01001548 // The top address of the frame is computed from the previous frame's top and
1549 // this frame's size.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001550 intptr_t top_address;
1551 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1552 output_frame->SetTop(top_address);
1553
1554 // Compute the incoming parameter translation.
1555 int parameter_count = height;
1556 unsigned output_offset = output_frame_size;
1557 for (int i = 0; i < parameter_count; ++i) {
1558 output_offset -= kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001559 // The allocated receiver of a construct stub frame is passed as the
1560 // receiver parameter through the translation. It might be encoding
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001561 // a captured object, override the slot address for a captured object.
1562 WriteTranslatedValueToOutput(
1563 &value_iterator, &input_index, frame_index, output_offset, nullptr,
1564 (i == 0) ? reinterpret_cast<Address>(top_address) : nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001565 }
1566
1567 // Read caller's PC from the previous frame.
1568 output_offset -= kPCOnStackSize;
1569 intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1570 output_frame->SetCallerPc(output_offset, callers_pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001571 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001572
1573 // Read caller's FP from the previous frame, and set this frame's FP.
1574 output_offset -= kFPOnStackSize;
1575 intptr_t value = output_[frame_index - 1]->GetFp();
1576 output_frame->SetCallerFp(output_offset, value);
1577 intptr_t fp_value = top_address + output_offset;
1578 output_frame->SetFp(fp_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001579 if (is_topmost) {
1580 Register fp_reg = JavaScriptFrame::fp_register();
1581 output_frame->SetRegister(fp_reg.code(), fp_value);
1582 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001583 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001584
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001585 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001586 // Read the caller's constant pool from the previous frame.
1587 output_offset -= kPointerSize;
1588 value = output_[frame_index - 1]->GetConstantPool();
1589 output_frame->SetCallerConstantPool(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001590 DebugPrintOutputSlot(value, frame_index, output_offset,
1591 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001592 }
1593
Ben Murdochda12d292016-06-02 14:46:10 +01001594 // A marker value is used to mark the frame.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001595 output_offset -= kPointerSize;
1596 value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT));
1597 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001598 DebugPrintOutputSlot(value, frame_index, output_offset,
Ben Murdochda12d292016-06-02 14:46:10 +01001599 "typed frame marker\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001600
Ben Murdochda12d292016-06-02 14:46:10 +01001601 // The context can be gotten from the previous frame.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001602 output_offset -= kPointerSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001603 value = output_[frame_index - 1]->GetContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001604 output_frame->SetFrameSlot(output_offset, value);
Ben Murdochda12d292016-06-02 14:46:10 +01001605 if (is_topmost) {
1606 Register context_reg = JavaScriptFrame::context_register();
1607 output_frame->SetRegister(context_reg.code(), value);
1608 }
1609 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001610
1611 // The allocation site.
1612 output_offset -= kPointerSize;
1613 value = reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value());
1614 output_frame->SetFrameSlot(output_offset, value);
1615 DebugPrintOutputSlot(value, frame_index, output_offset, "allocation site\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001616
1617 // Number of incoming arguments.
1618 output_offset -= kPointerSize;
1619 value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
1620 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001621 DebugPrintOutputSlot(value, frame_index, output_offset, "argc ");
1622 if (trace_scope_ != nullptr) {
1623 PrintF(trace_scope_->file(), "(%d)\n", height - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001624 }
1625
1626 // The newly allocated object was passed as receiver in the artificial
1627 // constructor stub environment created by HEnvironment::CopyForInlining().
1628 output_offset -= kPointerSize;
1629 value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
1630 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001631 DebugPrintOutputSlot(value, frame_index, output_offset,
1632 "allocated receiver\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001633
Ben Murdochda12d292016-06-02 14:46:10 +01001634 if (is_topmost) {
1635 // Ensure the result is restored back when we return to the stub.
1636 output_offset -= kPointerSize;
1637 Register result_reg = FullCodeGenerator::result_register();
1638 value = input_->GetRegister(result_reg.code());
1639 output_frame->SetFrameSlot(output_offset, value);
1640 DebugPrintOutputSlot(value, frame_index, output_offset,
1641 "constructor result\n");
1642
Ben Murdochc5610432016-08-08 18:44:38 +01001643 output_frame->SetState(
1644 Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER)));
Ben Murdochda12d292016-06-02 14:46:10 +01001645 }
1646
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001647 CHECK_EQ(0u, output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001648
1649 intptr_t pc = reinterpret_cast<intptr_t>(
1650 construct_stub->instruction_start() +
1651 isolate_->heap()->construct_stub_deopt_pc_offset()->value());
1652 output_frame->SetPc(pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001653 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001654 intptr_t constant_pool_value =
1655 reinterpret_cast<intptr_t>(construct_stub->constant_pool());
1656 output_frame->SetConstantPool(constant_pool_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001657 if (is_topmost) {
1658 Register constant_pool_reg =
1659 JavaScriptFrame::constant_pool_pointer_register();
1660 output_frame->SetRegister(constant_pool_reg.code(), fp_value);
1661 }
1662 }
1663
1664 // Set the continuation for the topmost frame.
1665 if (is_topmost) {
1666 Builtins* builtins = isolate_->builtins();
1667 DCHECK_EQ(LAZY, bailout_type_);
1668 Code* continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
1669 output_frame->SetContinuation(
1670 reinterpret_cast<intptr_t>(continuation->entry()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001671 }
1672}
1673
Ben Murdochda12d292016-06-02 14:46:10 +01001674void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
1675 int frame_index,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001676 bool is_setter_stub_frame) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001677 TranslatedFrame::iterator value_iterator = translated_frame->begin();
Ben Murdochda12d292016-06-02 14:46:10 +01001678 bool is_topmost = (output_count_ - 1 == frame_index);
1679 // The accessor frame could become topmost only if we inlined an accessor
1680 // call which does a tail call (otherwise the tail callee's frame would be
1681 // the topmost one). So it could only be the LAZY case.
1682 CHECK(!is_topmost || bailout_type_ == LAZY);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001683 int input_index = 0;
1684
Ben Murdoch097c5b22016-05-18 11:27:45 +01001685 // Skip accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001686 value_iterator++;
1687 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001688 // The receiver (and the implicit return value, if any) are expected in
1689 // registers by the LoadIC/StoreIC, so they don't belong to the output stack
1690 // frame. This means that we have to use a height of 0.
1691 unsigned height = 0;
1692 unsigned height_in_bytes = height * kPointerSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001693
1694 // If the accessor frame appears to be topmost we should ensure that the
1695 // value of result register is preserved during continuation execution.
1696 // We do this here by "pushing" the result of the accessor function to the
1697 // top of the reconstructed stack and then using the
Ben Murdochc5610432016-08-08 18:44:38 +01001698 // BailoutState::TOS_REGISTER machinery.
Ben Murdochda12d292016-06-02 14:46:10 +01001699 // We don't need to restore the result in case of a setter call because we
1700 // have to return the stored value but not the result of the setter function.
1701 bool should_preserve_result = is_topmost && !is_setter_stub_frame;
1702 if (should_preserve_result) {
1703 height_in_bytes += kPointerSize;
1704 }
1705
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001706 const char* kind = is_setter_stub_frame ? "setter" : "getter";
1707 if (trace_scope_ != NULL) {
1708 PrintF(trace_scope_->file(),
1709 " translating %s stub => height=%u\n", kind, height_in_bytes);
1710 }
1711
1712 // We need 1 stack entry for the return address and enough entries for the
Ben Murdochda12d292016-06-02 14:46:10 +01001713 // StackFrame::INTERNAL (FP, frame type, context, code object and constant
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001714 // pool (if enabled)- see MacroAssembler::EnterFrame).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001715 // For a setter stub frame we need one additional entry for the implicit
1716 // return value, see StoreStubCompiler::CompileStoreViaSetter.
1717 unsigned fixed_frame_entries =
1718 (StandardFrameConstants::kFixedFrameSize / kPointerSize) + 1 +
1719 (is_setter_stub_frame ? 1 : 0);
1720 unsigned fixed_frame_size = fixed_frame_entries * kPointerSize;
1721 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1722
1723 // Allocate and store the output frame description.
1724 FrameDescription* output_frame =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001725 new (output_frame_size) FrameDescription(output_frame_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001726 output_frame->SetFrameType(StackFrame::INTERNAL);
1727
Ben Murdochda12d292016-06-02 14:46:10 +01001728 // A frame for an accessor stub can not be bottommost.
1729 CHECK(frame_index > 0 && frame_index < output_count_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001730 CHECK_NULL(output_[frame_index]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001731 output_[frame_index] = output_frame;
1732
1733 // The top address of the frame is computed from the previous frame's top and
1734 // this frame's size.
1735 intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1736 output_frame->SetTop(top_address);
1737
1738 unsigned output_offset = output_frame_size;
1739
1740 // Read caller's PC from the previous frame.
1741 output_offset -= kPCOnStackSize;
1742 intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1743 output_frame->SetCallerPc(output_offset, callers_pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001744 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001745
1746 // Read caller's FP from the previous frame, and set this frame's FP.
1747 output_offset -= kFPOnStackSize;
1748 intptr_t value = output_[frame_index - 1]->GetFp();
1749 output_frame->SetCallerFp(output_offset, value);
1750 intptr_t fp_value = top_address + output_offset;
1751 output_frame->SetFp(fp_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001752 if (is_topmost) {
1753 Register fp_reg = JavaScriptFrame::fp_register();
1754 output_frame->SetRegister(fp_reg.code(), fp_value);
1755 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001756 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001757
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001758 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001759 // Read the caller's constant pool from the previous frame.
1760 output_offset -= kPointerSize;
1761 value = output_[frame_index - 1]->GetConstantPool();
1762 output_frame->SetCallerConstantPool(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001763 DebugPrintOutputSlot(value, frame_index, output_offset,
1764 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001765 }
1766
Ben Murdochda12d292016-06-02 14:46:10 +01001767 // Set the frame type.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001768 output_offset -= kPointerSize;
1769 value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::INTERNAL));
1770 output_frame->SetFrameSlot(output_offset, value);
Ben Murdochda12d292016-06-02 14:46:10 +01001771 DebugPrintOutputSlot(value, frame_index, output_offset, "frame type ");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001772 if (trace_scope_ != nullptr) {
1773 PrintF(trace_scope_->file(), "(%s sentinel)\n", kind);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001774 }
1775
1776 // Get Code object from accessor stub.
1777 output_offset -= kPointerSize;
1778 Builtins::Name name = is_setter_stub_frame ?
1779 Builtins::kStoreIC_Setter_ForDeopt :
1780 Builtins::kLoadIC_Getter_ForDeopt;
1781 Code* accessor_stub = isolate_->builtins()->builtin(name);
1782 value = reinterpret_cast<intptr_t>(accessor_stub);
1783 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001784 DebugPrintOutputSlot(value, frame_index, output_offset, "code object\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001785
Ben Murdochda12d292016-06-02 14:46:10 +01001786 // The context can be gotten from the previous frame.
1787 output_offset -= kPointerSize;
1788 value = output_[frame_index - 1]->GetContext();
1789 output_frame->SetFrameSlot(output_offset, value);
1790 if (is_topmost) {
1791 Register context_reg = JavaScriptFrame::context_register();
1792 output_frame->SetRegister(context_reg.code(), value);
1793 }
1794 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
1795
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001796 // Skip receiver.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001797 value_iterator++;
1798 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001799
1800 if (is_setter_stub_frame) {
1801 // The implicit return value was part of the artificial setter stub
1802 // environment.
1803 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001804 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1805 output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001806 }
1807
Ben Murdochda12d292016-06-02 14:46:10 +01001808 if (should_preserve_result) {
1809 // Ensure the result is restored back when we return to the stub.
1810 output_offset -= kPointerSize;
1811 Register result_reg = FullCodeGenerator::result_register();
1812 value = input_->GetRegister(result_reg.code());
1813 output_frame->SetFrameSlot(output_offset, value);
1814 DebugPrintOutputSlot(value, frame_index, output_offset,
1815 "accessor result\n");
1816
Ben Murdochc5610432016-08-08 18:44:38 +01001817 output_frame->SetState(
1818 Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER)));
Ben Murdochda12d292016-06-02 14:46:10 +01001819 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01001820 output_frame->SetState(
1821 Smi::FromInt(static_cast<int>(BailoutState::NO_REGISTERS)));
Ben Murdochda12d292016-06-02 14:46:10 +01001822 }
1823
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001824 CHECK_EQ(0u, output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001825
1826 Smi* offset = is_setter_stub_frame ?
1827 isolate_->heap()->setter_stub_deopt_pc_offset() :
1828 isolate_->heap()->getter_stub_deopt_pc_offset();
1829 intptr_t pc = reinterpret_cast<intptr_t>(
1830 accessor_stub->instruction_start() + offset->value());
1831 output_frame->SetPc(pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001832 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001833 intptr_t constant_pool_value =
1834 reinterpret_cast<intptr_t>(accessor_stub->constant_pool());
1835 output_frame->SetConstantPool(constant_pool_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001836 if (is_topmost) {
1837 Register constant_pool_reg =
1838 JavaScriptFrame::constant_pool_pointer_register();
1839 output_frame->SetRegister(constant_pool_reg.code(), fp_value);
1840 }
1841 }
1842
1843 // Set the continuation for the topmost frame.
1844 if (is_topmost) {
1845 Builtins* builtins = isolate_->builtins();
1846 DCHECK_EQ(LAZY, bailout_type_);
1847 Code* continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
1848 output_frame->SetContinuation(
1849 reinterpret_cast<intptr_t>(continuation->entry()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001850 }
1851}
1852
Ben Murdochda12d292016-06-02 14:46:10 +01001853void Deoptimizer::DoComputeCompiledStubFrame(TranslatedFrame* translated_frame,
1854 int frame_index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001855 //
1856 // FROM TO
1857 // | .... | | .... |
1858 // +-------------------------+ +-------------------------+
1859 // | JSFunction continuation | | JSFunction continuation |
1860 // +-------------------------+ +-------------------------+
1861 // | | saved frame (FP) | | saved frame (FP) |
1862 // | +=========================+<-fpreg +=========================+<-fpreg
1863 // | |constant pool (if ool_cp)| |constant pool (if ool_cp)|
1864 // | +-------------------------+ +-------------------------|
1865 // | | JSFunction context | | JSFunction context |
1866 // v +-------------------------+ +-------------------------|
1867 // | COMPILED_STUB marker | | STUB_FAILURE marker |
1868 // +-------------------------+ +-------------------------+
1869 // | | | caller args.arguments_ |
1870 // | ... | +-------------------------+
1871 // | | | caller args.length_ |
1872 // |-------------------------|<-spreg +-------------------------+
1873 // | caller args pointer |
1874 // +-------------------------+
1875 // | caller stack param 1 |
1876 // parameters in registers +-------------------------+
1877 // and spilled to stack | .... |
1878 // +-------------------------+
1879 // | caller stack param n |
1880 // +-------------------------+<-spreg
1881 // reg = number of parameters
1882 // reg = failure handler address
1883 // reg = saved frame
1884 // reg = JSFunction context
1885 //
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001886 // Caller stack params contain the register parameters to the stub first,
1887 // and then, if the descriptor specifies a constant number of stack
1888 // parameters, the stack parameters as well.
1889
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001890 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1891 int input_index = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001892
1893 CHECK(compiled_code_->is_hydrogen_stub());
1894 int major_key = CodeStub::GetMajorKey(compiled_code_);
1895 CodeStubDescriptor descriptor(isolate_, compiled_code_->stub_key());
1896
1897 // The output frame must have room for all pushed register parameters
1898 // and the standard stack frame slots. Include space for an argument
1899 // object to the callee and optionally the space to pass the argument
1900 // object to the stub failure handler.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001901 int param_count = descriptor.GetRegisterParameterCount();
1902 int stack_param_count = descriptor.GetStackParameterCount();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001903 // The translated frame contains all of the register parameters
1904 // plus the context.
1905 CHECK_EQ(translated_frame->height(), param_count + 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001906 CHECK_GE(param_count, 0);
1907
Ben Murdochda12d292016-06-02 14:46:10 +01001908 int height_in_bytes = kPointerSize * (param_count + stack_param_count);
1909 int fixed_frame_size = StubFailureTrampolineFrameConstants::kFixedFrameSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001910 int output_frame_size = height_in_bytes + fixed_frame_size;
1911 if (trace_scope_ != NULL) {
1912 PrintF(trace_scope_->file(),
1913 " translating %s => StubFailureTrampolineStub, height=%d\n",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001914 CodeStub::MajorName(static_cast<CodeStub::Major>(major_key)),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001915 height_in_bytes);
1916 }
1917
1918 // The stub failure trampoline is a single frame.
1919 FrameDescription* output_frame =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001920 new (output_frame_size) FrameDescription(output_frame_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001921 output_frame->SetFrameType(StackFrame::STUB_FAILURE_TRAMPOLINE);
1922 CHECK_EQ(frame_index, 0);
1923 output_[frame_index] = output_frame;
1924
Ben Murdochda12d292016-06-02 14:46:10 +01001925 // The top address of the frame is computed from the previous frame's top and
1926 // this frame's size.
1927 intptr_t top_address = caller_frame_top_ - output_frame_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001928 output_frame->SetTop(top_address);
1929
Ben Murdochda12d292016-06-02 14:46:10 +01001930 // Set caller's PC (JSFunction continuation).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001931 unsigned output_frame_offset = output_frame_size - kFPOnStackSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001932 intptr_t value = caller_pc_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001933 output_frame->SetCallerPc(output_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001934 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
1935 "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001936
1937 // Read caller's FP from the input frame, and set this frame's FP.
Ben Murdochda12d292016-06-02 14:46:10 +01001938 value = caller_fp_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001939 output_frame_offset -= kFPOnStackSize;
1940 output_frame->SetCallerFp(output_frame_offset, value);
Ben Murdochda12d292016-06-02 14:46:10 +01001941 intptr_t frame_ptr = top_address + output_frame_offset;
1942 Register fp_reg = StubFailureTrampolineFrame::fp_register();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001943 output_frame->SetRegister(fp_reg.code(), frame_ptr);
1944 output_frame->SetFp(frame_ptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001945 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
1946 "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001947
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001948 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001949 // Read the caller's constant pool from the input frame.
Ben Murdochda12d292016-06-02 14:46:10 +01001950 value = caller_constant_pool_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001951 output_frame_offset -= kPointerSize;
1952 output_frame->SetCallerConstantPool(output_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001953 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
1954 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001955 }
1956
Ben Murdochda12d292016-06-02 14:46:10 +01001957 // The marker for the typed stack frame
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001958 output_frame_offset -= kPointerSize;
1959 value = reinterpret_cast<intptr_t>(
1960 Smi::FromInt(StackFrame::STUB_FAILURE_TRAMPOLINE));
1961 output_frame->SetFrameSlot(output_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001962 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
1963 "function (stub failure sentinel)\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001964
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001965 intptr_t caller_arg_count = stack_param_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001966 bool arg_count_known = !descriptor.stack_parameter_count().is_valid();
1967
1968 // Build the Arguments object for the caller's parameters and a pointer to it.
1969 output_frame_offset -= kPointerSize;
1970 int args_arguments_offset = output_frame_offset;
1971 intptr_t the_hole = reinterpret_cast<intptr_t>(
1972 isolate_->heap()->the_hole_value());
1973 if (arg_count_known) {
1974 value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
1975 (caller_arg_count - 1) * kPointerSize;
1976 } else {
1977 value = the_hole;
1978 }
1979
1980 output_frame->SetFrameSlot(args_arguments_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001981 DebugPrintOutputSlot(
1982 value, frame_index, args_arguments_offset,
1983 arg_count_known ? "args.arguments\n" : "args.arguments (the hole)\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001984
1985 output_frame_offset -= kPointerSize;
1986 int length_frame_offset = output_frame_offset;
1987 value = arg_count_known ? caller_arg_count : the_hole;
1988 output_frame->SetFrameSlot(length_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001989 DebugPrintOutputSlot(
1990 value, frame_index, length_frame_offset,
1991 arg_count_known ? "args.length\n" : "args.length (the hole)\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001992
1993 output_frame_offset -= kPointerSize;
1994 value = frame_ptr + StandardFrameConstants::kCallerSPOffset -
1995 (output_frame_size - output_frame_offset) + kPointerSize;
1996 output_frame->SetFrameSlot(output_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001997 DebugPrintOutputSlot(value, frame_index, output_frame_offset, "args*\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001998
1999 // Copy the register parameters to the failure frame.
2000 int arguments_length_offset = -1;
2001 for (int i = 0; i < param_count; ++i) {
2002 output_frame_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002003 WriteTranslatedValueToOutput(&value_iterator, &input_index, 0,
2004 output_frame_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002005
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002006 if (!arg_count_known &&
2007 descriptor.GetRegisterParameter(i)
2008 .is(descriptor.stack_parameter_count())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002009 arguments_length_offset = output_frame_offset;
2010 }
2011 }
2012
Ben Murdoch097c5b22016-05-18 11:27:45 +01002013 Object* maybe_context = value_iterator->GetRawValue();
2014 CHECK(maybe_context->IsContext());
2015 Register context_reg = StubFailureTrampolineFrame::context_register();
2016 value = reinterpret_cast<intptr_t>(maybe_context);
2017 output_frame->SetRegister(context_reg.code(), value);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002018 ++value_iterator;
2019
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002020 // Copy constant stack parameters to the failure frame. If the number of stack
2021 // parameters is not known in the descriptor, the arguments object is the way
2022 // to access them.
2023 for (int i = 0; i < stack_param_count; i++) {
2024 output_frame_offset -= kPointerSize;
2025 Object** stack_parameter = reinterpret_cast<Object**>(
2026 frame_ptr + StandardFrameConstants::kCallerSPOffset +
2027 (stack_param_count - i - 1) * kPointerSize);
2028 value = reinterpret_cast<intptr_t>(*stack_parameter);
2029 output_frame->SetFrameSlot(output_frame_offset, value);
2030 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
2031 "stack parameter\n");
2032 }
2033
2034 CHECK_EQ(0u, output_frame_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002035
2036 if (!arg_count_known) {
2037 CHECK_GE(arguments_length_offset, 0);
2038 // We know it's a smi because 1) the code stub guarantees the stack
2039 // parameter count is in smi range, and 2) the DoTranslateCommand in the
2040 // parameter loop above translated that to a tagged value.
2041 Smi* smi_caller_arg_count = reinterpret_cast<Smi*>(
2042 output_frame->GetFrameSlot(arguments_length_offset));
2043 caller_arg_count = smi_caller_arg_count->value();
2044 output_frame->SetFrameSlot(length_frame_offset, caller_arg_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002045 DebugPrintOutputSlot(caller_arg_count, frame_index, length_frame_offset,
2046 "args.length\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002047 value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
2048 (caller_arg_count - 1) * kPointerSize;
2049 output_frame->SetFrameSlot(args_arguments_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002050 DebugPrintOutputSlot(value, frame_index, args_arguments_offset,
2051 "args.arguments");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002052 }
2053
2054 // Copy the double registers from the input into the output frame.
2055 CopyDoubleRegisters(output_frame);
2056
2057 // Fill registers containing handler and number of parameters.
2058 SetPlatformCompiledStubRegisters(output_frame, &descriptor);
2059
2060 // Compute this frame's PC, state, and continuation.
2061 Code* trampoline = NULL;
2062 StubFunctionMode function_mode = descriptor.function_mode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002063 StubFailureTrampolineStub(isolate_, function_mode)
2064 .FindCodeInCache(&trampoline);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002065 DCHECK(trampoline != NULL);
2066 output_frame->SetPc(reinterpret_cast<intptr_t>(
2067 trampoline->instruction_start()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002068 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002069 Register constant_pool_reg =
2070 StubFailureTrampolineFrame::constant_pool_pointer_register();
2071 intptr_t constant_pool_value =
2072 reinterpret_cast<intptr_t>(trampoline->constant_pool());
2073 output_frame->SetConstantPool(constant_pool_value);
2074 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
2075 }
Ben Murdochc5610432016-08-08 18:44:38 +01002076 output_frame->SetState(
2077 Smi::FromInt(static_cast<int>(BailoutState::NO_REGISTERS)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002078 Code* notify_failure =
2079 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles);
2080 output_frame->SetContinuation(
2081 reinterpret_cast<intptr_t>(notify_failure->entry()));
2082}
2083
2084
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002085void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002086 // Walk to the last JavaScript output frame to find out if it has
2087 // adapted arguments.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002088 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
2089 if (frame_index != 0) it->Advance();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002090 }
Ben Murdochda12d292016-06-02 14:46:10 +01002091 translated_state_.Prepare(it->frame()->has_adapted_arguments(),
2092 reinterpret_cast<Address>(stack_fp_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002093
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002094 for (auto& materialization : values_to_materialize_) {
2095 Handle<Object> value = materialization.value_->GetValue();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002096
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002097 if (trace_scope_ != nullptr) {
2098 PrintF("Materialization [0x%08" V8PRIxPTR "] <- 0x%08" V8PRIxPTR " ; ",
2099 reinterpret_cast<intptr_t>(materialization.output_slot_address_),
2100 reinterpret_cast<intptr_t>(*value));
2101 value->ShortPrint(trace_scope_->file());
2102 PrintF(trace_scope_->file(), "\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002103 }
2104
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002105 *(reinterpret_cast<intptr_t*>(materialization.output_slot_address_)) =
2106 reinterpret_cast<intptr_t>(*value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002107 }
2108
Ben Murdochda12d292016-06-02 14:46:10 +01002109 isolate_->materialized_object_store()->Remove(
2110 reinterpret_cast<Address>(stack_fp_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002111}
2112
2113
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002114void Deoptimizer::WriteTranslatedValueToOutput(
2115 TranslatedFrame::iterator* iterator, int* input_index, int frame_index,
2116 unsigned output_offset, const char* debug_hint_string,
2117 Address output_address_for_materialization) {
2118 Object* value = (*iterator)->GetRawValue();
2119
2120 WriteValueToOutput(value, *input_index, frame_index, output_offset,
2121 debug_hint_string);
2122
2123 if (value == isolate_->heap()->arguments_marker()) {
2124 Address output_address =
2125 reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
2126 output_offset;
2127 if (output_address_for_materialization == nullptr) {
2128 output_address_for_materialization = output_address;
2129 }
2130 values_to_materialize_.push_back(
2131 {output_address_for_materialization, *iterator});
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002132 }
2133
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002134 (*iterator)++;
2135 (*input_index)++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002136}
2137
2138
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002139void Deoptimizer::WriteValueToOutput(Object* value, int input_index,
2140 int frame_index, unsigned output_offset,
2141 const char* debug_hint_string) {
2142 output_[frame_index]->SetFrameSlot(output_offset,
2143 reinterpret_cast<intptr_t>(value));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002144
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002145 if (trace_scope_ != nullptr) {
2146 DebugPrintOutputSlot(reinterpret_cast<intptr_t>(value), frame_index,
2147 output_offset, debug_hint_string);
2148 value->ShortPrint(trace_scope_->file());
2149 PrintF(trace_scope_->file(), " (input #%d)\n", input_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002150 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002151}
2152
2153
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002154void Deoptimizer::DebugPrintOutputSlot(intptr_t value, int frame_index,
2155 unsigned output_offset,
2156 const char* debug_hint_string) {
2157 if (trace_scope_ != nullptr) {
2158 Address output_address =
2159 reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
2160 output_offset;
2161 PrintF(trace_scope_->file(),
2162 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s",
2163 reinterpret_cast<intptr_t>(output_address), output_offset, value,
2164 debug_hint_string == nullptr ? "" : debug_hint_string);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002165 }
2166}
2167
Ben Murdochda12d292016-06-02 14:46:10 +01002168unsigned Deoptimizer::ComputeInputFrameAboveFpFixedSize() const {
2169 unsigned fixed_size = CommonFrameConstants::kFixedFrameSizeAboveFp;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002170 if (!function_->IsSmi()) {
2171 fixed_size += ComputeIncomingArgumentSize(function_->shared());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002172 }
Ben Murdochda12d292016-06-02 14:46:10 +01002173 return fixed_size;
2174}
2175
2176unsigned Deoptimizer::ComputeInputFrameSize() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002177 // The fp-to-sp delta already takes the context, constant pool pointer and the
2178 // function into account so we have to avoid double counting them.
Ben Murdochda12d292016-06-02 14:46:10 +01002179 unsigned fixed_size_above_fp = ComputeInputFrameAboveFpFixedSize();
2180 unsigned result = fixed_size_above_fp + fp_to_sp_delta_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002181 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
2182 unsigned stack_slots = compiled_code_->stack_slots();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002183 unsigned outgoing_size =
2184 ComputeOutgoingArgumentSize(compiled_code_, bailout_id_);
Ben Murdochda12d292016-06-02 14:46:10 +01002185 CHECK_EQ(fixed_size_above_fp + (stack_slots * kPointerSize) -
2186 CommonFrameConstants::kFixedFrameSizeAboveFp + outgoing_size,
2187 result);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002188 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01002189 return result;
2190}
2191
Ben Murdoch097c5b22016-05-18 11:27:45 +01002192// static
2193unsigned Deoptimizer::ComputeJavascriptFixedSize(SharedFunctionInfo* shared) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002194 // The fixed part of the frame consists of the return address, frame
2195 // pointer, function, context, and all the incoming arguments.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002196 return ComputeIncomingArgumentSize(shared) +
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002197 StandardFrameConstants::kFixedFrameSize;
2198}
2199
Ben Murdoch097c5b22016-05-18 11:27:45 +01002200// static
2201unsigned Deoptimizer::ComputeInterpretedFixedSize(SharedFunctionInfo* shared) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002202 // The fixed part of the frame consists of the return address, frame
2203 // pointer, function, context, new.target, bytecode offset and all the
2204 // incoming arguments.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002205 return ComputeIncomingArgumentSize(shared) +
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002206 InterpreterFrameConstants::kFixedFrameSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002207}
2208
Ben Murdoch097c5b22016-05-18 11:27:45 +01002209// static
2210unsigned Deoptimizer::ComputeIncomingArgumentSize(SharedFunctionInfo* shared) {
2211 return (shared->internal_formal_parameter_count() + 1) * kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002212}
2213
2214
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002215// static
2216unsigned Deoptimizer::ComputeOutgoingArgumentSize(Code* code,
2217 unsigned bailout_id) {
2218 DeoptimizationInputData* data =
2219 DeoptimizationInputData::cast(code->deoptimization_data());
2220 unsigned height = data->ArgumentsStackHeight(bailout_id)->value();
Ben Murdochb0fe1622011-05-05 13:52:32 +01002221 return height * kPointerSize;
2222}
2223
2224
2225Object* Deoptimizer::ComputeLiteral(int index) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002226 DeoptimizationInputData* data =
2227 DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002228 FixedArray* literals = data->LiteralArray();
2229 return literals->get(index);
2230}
2231
2232
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002233void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate,
2234 BailoutType type,
2235 int max_entry_id) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002236 // We cannot run this if the serializer is enabled because this will
2237 // cause us to emit relocation information for the external
2238 // references. This is fine because the deoptimizer's code section
2239 // isn't meant to be serialized at all.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002240 CHECK(type == EAGER || type == SOFT || type == LAZY);
2241 DeoptimizerData* data = isolate->deoptimizer_data();
2242 int entry_count = data->deopt_entry_code_entries_[type];
2243 if (max_entry_id < entry_count) return;
2244 entry_count = Max(entry_count, Deoptimizer::kMinNumberOfEntries);
2245 while (max_entry_id >= entry_count) entry_count *= 2;
2246 CHECK(entry_count <= Deoptimizer::kMaxNumberOfEntries);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002247
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002248 MacroAssembler masm(isolate, NULL, 16 * KB, CodeObjectRequired::kYes);
Steve Block44f0eee2011-05-26 01:26:41 +01002249 masm.set_emit_debug_code(false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002250 GenerateDeoptimizationEntries(&masm, entry_count, type);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002251 CodeDesc desc;
2252 masm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002253 DCHECK(!RelocInfo::RequiresRelocation(desc));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002254
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002255 MemoryChunk* chunk = data->deopt_entry_code_[type];
2256 CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >=
2257 desc.instr_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002258 if (!chunk->CommitArea(desc.instr_size)) {
2259 V8::FatalProcessOutOfMemory(
2260 "Deoptimizer::EnsureCodeForDeoptimizationEntry");
2261 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002262 CopyBytes(chunk->area_start(), desc.buffer,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002263 static_cast<size_t>(desc.instr_size));
2264 Assembler::FlushICache(isolate, chunk->area_start(), desc.instr_size);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002265
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002266 data->deopt_entry_code_entries_[type] = entry_count;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002267}
2268
Ben Murdoch097c5b22016-05-18 11:27:45 +01002269FrameDescription::FrameDescription(uint32_t frame_size, int parameter_count)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002270 : frame_size_(frame_size),
Ben Murdoch097c5b22016-05-18 11:27:45 +01002271 parameter_count_(parameter_count),
Ben Murdochb0fe1622011-05-05 13:52:32 +01002272 top_(kZapUint32),
2273 pc_(kZapUint32),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002274 fp_(kZapUint32),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002275 context_(kZapUint32),
2276 constant_pool_(kZapUint32) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002277 // Zap all the registers.
2278 for (int r = 0; r < Register::kNumRegisters; r++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002279 // TODO(jbramley): It isn't safe to use kZapUint32 here. If the register
2280 // isn't used before the next safepoint, the GC will try to scan it as a
2281 // tagged value. kZapUint32 looks like a valid tagged pointer, but it isn't.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002282 SetRegister(r, kZapUint32);
2283 }
2284
2285 // Zap all the slots.
2286 for (unsigned o = 0; o < frame_size; o += kPointerSize) {
2287 SetFrameSlot(o, kZapUint32);
2288 }
2289}
2290
2291
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002292int FrameDescription::ComputeFixedSize() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002293 if (type_ == StackFrame::INTERPRETED) {
2294 return InterpreterFrameConstants::kFixedFrameSize +
Ben Murdoch097c5b22016-05-18 11:27:45 +01002295 parameter_count() * kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002296 } else {
2297 return StandardFrameConstants::kFixedFrameSize +
Ben Murdoch097c5b22016-05-18 11:27:45 +01002298 parameter_count() * kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002299 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002300}
2301
2302
2303unsigned FrameDescription::GetOffsetFromSlotIndex(int slot_index) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002304 if (slot_index >= 0) {
2305 // Local or spill slots. Skip the fixed part of the frame
2306 // including all arguments.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002307 unsigned base = GetFrameSize() - ComputeFixedSize();
Ben Murdochb0fe1622011-05-05 13:52:32 +01002308 return base - ((slot_index + 1) * kPointerSize);
2309 } else {
2310 // Incoming parameter.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002311 int arg_size = parameter_count() * kPointerSize;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002312 unsigned base = GetFrameSize() - arg_size;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002313 return base - ((slot_index + 1) * kPointerSize);
2314 }
2315}
2316
2317
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002318void TranslationBuffer::Add(int32_t value, Zone* zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002319 // This wouldn't handle kMinInt correctly if it ever encountered it.
2320 DCHECK(value != kMinInt);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002321 // Encode the sign bit in the least significant bit.
2322 bool is_negative = (value < 0);
2323 uint32_t bits = ((is_negative ? -value : value) << 1) |
2324 static_cast<int32_t>(is_negative);
2325 // Encode the individual bytes using the least significant bit of
2326 // each byte to indicate whether or not more bytes follow.
2327 do {
2328 uint32_t next = bits >> 7;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002329 contents_.Add(((bits << 1) & 0xFF) | (next != 0), zone);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002330 bits = next;
2331 } while (bits != 0);
2332}
2333
2334
2335int32_t TranslationIterator::Next() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002336 // Run through the bytes until we reach one with a least significant
2337 // bit of zero (marks the end).
2338 uint32_t bits = 0;
2339 for (int i = 0; true; i += 7) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002340 DCHECK(HasNext());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002341 uint8_t next = buffer_->get(index_++);
2342 bits |= (next >> 1) << i;
2343 if ((next & 1) == 0) break;
2344 }
2345 // The bits encode the sign in the least significant bit.
2346 bool is_negative = (bits & 1) == 1;
2347 int32_t result = bits >> 1;
2348 return is_negative ? -result : result;
2349}
2350
2351
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002352Handle<ByteArray> TranslationBuffer::CreateByteArray(Factory* factory) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002353 int length = contents_.length();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002354 Handle<ByteArray> result = factory->NewByteArray(length, TENURED);
2355 MemCopy(result->GetDataStartAddress(), contents_.ToVector().start(), length);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002356 return result;
2357}
2358
2359
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002360void Translation::BeginConstructStubFrame(int literal_id, unsigned height) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002361 buffer_->Add(CONSTRUCT_STUB_FRAME, zone());
2362 buffer_->Add(literal_id, zone());
2363 buffer_->Add(height, zone());
2364}
2365
2366
2367void Translation::BeginGetterStubFrame(int literal_id) {
2368 buffer_->Add(GETTER_STUB_FRAME, zone());
2369 buffer_->Add(literal_id, zone());
2370}
2371
2372
2373void Translation::BeginSetterStubFrame(int literal_id) {
2374 buffer_->Add(SETTER_STUB_FRAME, zone());
2375 buffer_->Add(literal_id, zone());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002376}
2377
2378
2379void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002380 buffer_->Add(ARGUMENTS_ADAPTOR_FRAME, zone());
2381 buffer_->Add(literal_id, zone());
2382 buffer_->Add(height, zone());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002383}
2384
Ben Murdochda12d292016-06-02 14:46:10 +01002385void Translation::BeginTailCallerFrame(int literal_id) {
2386 buffer_->Add(TAIL_CALLER_FRAME, zone());
2387 buffer_->Add(literal_id, zone());
2388}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002389
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002390void Translation::BeginJSFrame(BailoutId node_id,
2391 int literal_id,
2392 unsigned height) {
2393 buffer_->Add(JS_FRAME, zone());
2394 buffer_->Add(node_id.ToInt(), zone());
2395 buffer_->Add(literal_id, zone());
2396 buffer_->Add(height, zone());
2397}
2398
2399
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002400void Translation::BeginInterpretedFrame(BailoutId bytecode_offset,
2401 int literal_id, unsigned height) {
2402 buffer_->Add(INTERPRETED_FRAME, zone());
2403 buffer_->Add(bytecode_offset.ToInt(), zone());
2404 buffer_->Add(literal_id, zone());
2405 buffer_->Add(height, zone());
2406}
2407
2408
2409void Translation::BeginCompiledStubFrame(int height) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002410 buffer_->Add(COMPILED_STUB_FRAME, zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002411 buffer_->Add(height, zone());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002412}
2413
2414
2415void Translation::BeginArgumentsObject(int args_length) {
2416 buffer_->Add(ARGUMENTS_OBJECT, zone());
2417 buffer_->Add(args_length, zone());
2418}
2419
2420
2421void Translation::BeginCapturedObject(int length) {
2422 buffer_->Add(CAPTURED_OBJECT, zone());
2423 buffer_->Add(length, zone());
2424}
2425
2426
2427void Translation::DuplicateObject(int object_index) {
2428 buffer_->Add(DUPLICATED_OBJECT, zone());
2429 buffer_->Add(object_index, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002430}
2431
2432
2433void Translation::StoreRegister(Register reg) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002434 buffer_->Add(REGISTER, zone());
2435 buffer_->Add(reg.code(), zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002436}
2437
2438
2439void Translation::StoreInt32Register(Register reg) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002440 buffer_->Add(INT32_REGISTER, zone());
2441 buffer_->Add(reg.code(), zone());
2442}
2443
2444
2445void Translation::StoreUint32Register(Register reg) {
2446 buffer_->Add(UINT32_REGISTER, zone());
2447 buffer_->Add(reg.code(), zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002448}
2449
2450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002451void Translation::StoreBoolRegister(Register reg) {
2452 buffer_->Add(BOOL_REGISTER, zone());
2453 buffer_->Add(reg.code(), zone());
2454}
2455
Ben Murdoch61f157c2016-09-16 13:49:30 +01002456void Translation::StoreFloatRegister(FloatRegister reg) {
2457 buffer_->Add(FLOAT_REGISTER, zone());
2458 buffer_->Add(reg.code(), zone());
2459}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002460
Ben Murdochb0fe1622011-05-05 13:52:32 +01002461void Translation::StoreDoubleRegister(DoubleRegister reg) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002462 buffer_->Add(DOUBLE_REGISTER, zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002463 buffer_->Add(reg.code(), zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002464}
2465
2466
2467void Translation::StoreStackSlot(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002468 buffer_->Add(STACK_SLOT, zone());
2469 buffer_->Add(index, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002470}
2471
2472
2473void Translation::StoreInt32StackSlot(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002474 buffer_->Add(INT32_STACK_SLOT, zone());
2475 buffer_->Add(index, zone());
2476}
2477
2478
2479void Translation::StoreUint32StackSlot(int index) {
2480 buffer_->Add(UINT32_STACK_SLOT, zone());
2481 buffer_->Add(index, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002482}
2483
2484
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002485void Translation::StoreBoolStackSlot(int index) {
2486 buffer_->Add(BOOL_STACK_SLOT, zone());
2487 buffer_->Add(index, zone());
2488}
2489
Ben Murdoch61f157c2016-09-16 13:49:30 +01002490void Translation::StoreFloatStackSlot(int index) {
2491 buffer_->Add(FLOAT_STACK_SLOT, zone());
2492 buffer_->Add(index, zone());
2493}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002494
Ben Murdochb0fe1622011-05-05 13:52:32 +01002495void Translation::StoreDoubleStackSlot(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002496 buffer_->Add(DOUBLE_STACK_SLOT, zone());
2497 buffer_->Add(index, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002498}
2499
2500
2501void Translation::StoreLiteral(int literal_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002502 buffer_->Add(LITERAL, zone());
2503 buffer_->Add(literal_id, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002504}
2505
2506
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002507void Translation::StoreArgumentsObject(bool args_known,
2508 int args_index,
2509 int args_length) {
2510 buffer_->Add(ARGUMENTS_OBJECT, zone());
2511 buffer_->Add(args_known, zone());
2512 buffer_->Add(args_index, zone());
2513 buffer_->Add(args_length, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002514}
2515
2516
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002517void Translation::StoreJSFrameFunction() {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002518 StoreStackSlot((StandardFrameConstants::kCallerPCOffset -
Ben Murdochda12d292016-06-02 14:46:10 +01002519 StandardFrameConstants::kFunctionOffset) /
Ben Murdoch097c5b22016-05-18 11:27:45 +01002520 kPointerSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002521}
2522
Ben Murdochb0fe1622011-05-05 13:52:32 +01002523int Translation::NumberOfOperandsFor(Opcode opcode) {
2524 switch (opcode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002525 case GETTER_STUB_FRAME:
2526 case SETTER_STUB_FRAME:
2527 case DUPLICATED_OBJECT:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002528 case ARGUMENTS_OBJECT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002529 case CAPTURED_OBJECT:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002530 case REGISTER:
2531 case INT32_REGISTER:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002532 case UINT32_REGISTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002533 case BOOL_REGISTER:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002534 case FLOAT_REGISTER:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002535 case DOUBLE_REGISTER:
2536 case STACK_SLOT:
2537 case INT32_STACK_SLOT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002538 case UINT32_STACK_SLOT:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002539 case BOOL_STACK_SLOT:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002540 case FLOAT_STACK_SLOT:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002541 case DOUBLE_STACK_SLOT:
2542 case LITERAL:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002543 case COMPILED_STUB_FRAME:
Ben Murdochda12d292016-06-02 14:46:10 +01002544 case TAIL_CALLER_FRAME:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002545 return 1;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002546 case BEGIN:
2547 case ARGUMENTS_ADAPTOR_FRAME:
2548 case CONSTRUCT_STUB_FRAME:
2549 return 2;
2550 case JS_FRAME:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002551 case INTERPRETED_FRAME:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002552 return 3;
2553 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002554 FATAL("Unexpected translation type");
Ben Murdochb0fe1622011-05-05 13:52:32 +01002555 return -1;
2556}
2557
2558
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002559#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002560
2561const char* Translation::StringFor(Opcode opcode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002562#define TRANSLATION_OPCODE_CASE(item) case item: return #item;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002563 switch (opcode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002564 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002565 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002566#undef TRANSLATION_OPCODE_CASE
Ben Murdochb0fe1622011-05-05 13:52:32 +01002567 UNREACHABLE();
2568 return "";
2569}
2570
2571#endif
2572
2573
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002574Handle<FixedArray> MaterializedObjectStore::Get(Address fp) {
2575 int index = StackIdToIndex(fp);
2576 if (index == -1) {
2577 return Handle<FixedArray>::null();
2578 }
2579 Handle<FixedArray> array = GetStackEntries();
2580 CHECK_GT(array->length(), index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002581 return Handle<FixedArray>::cast(Handle<Object>(array->get(index), isolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002582}
2583
2584
2585void MaterializedObjectStore::Set(Address fp,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002586 Handle<FixedArray> materialized_objects) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002587 int index = StackIdToIndex(fp);
2588 if (index == -1) {
2589 index = frame_fps_.length();
2590 frame_fps_.Add(fp);
2591 }
2592
2593 Handle<FixedArray> array = EnsureStackEntries(index + 1);
2594 array->set(index, *materialized_objects);
2595}
2596
2597
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002598bool MaterializedObjectStore::Remove(Address fp) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002599 int index = StackIdToIndex(fp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002600 if (index == -1) {
2601 return false;
2602 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002603 CHECK_GE(index, 0);
2604
2605 frame_fps_.Remove(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002606 FixedArray* array = isolate()->heap()->materialized_objects();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002607 CHECK_LT(index, array->length());
2608 for (int i = index; i < frame_fps_.length(); i++) {
2609 array->set(i, array->get(i + 1));
2610 }
2611 array->set(frame_fps_.length(), isolate()->heap()->undefined_value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002612 return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002613}
2614
2615
2616int MaterializedObjectStore::StackIdToIndex(Address fp) {
2617 for (int i = 0; i < frame_fps_.length(); i++) {
2618 if (frame_fps_[i] == fp) {
2619 return i;
2620 }
2621 }
2622 return -1;
2623}
2624
2625
2626Handle<FixedArray> MaterializedObjectStore::GetStackEntries() {
2627 return Handle<FixedArray>(isolate()->heap()->materialized_objects());
2628}
2629
2630
2631Handle<FixedArray> MaterializedObjectStore::EnsureStackEntries(int length) {
2632 Handle<FixedArray> array = GetStackEntries();
2633 if (array->length() >= length) {
2634 return array;
2635 }
2636
2637 int new_length = length > 10 ? length : 10;
2638 if (new_length < 2 * array->length()) {
2639 new_length = 2 * array->length();
2640 }
2641
2642 Handle<FixedArray> new_array =
2643 isolate()->factory()->NewFixedArray(new_length, TENURED);
2644 for (int i = 0; i < array->length(); i++) {
2645 new_array->set(i, array->get(i));
2646 }
2647 for (int i = array->length(); i < length; i++) {
2648 new_array->set(i, isolate()->heap()->undefined_value());
2649 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002650 isolate()->heap()->SetRootMaterializedObjects(*new_array);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002651 return new_array;
2652}
2653
Ben Murdoch097c5b22016-05-18 11:27:45 +01002654namespace {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002655
Ben Murdoch097c5b22016-05-18 11:27:45 +01002656Handle<Object> GetValueForDebugger(TranslatedFrame::iterator it,
2657 Isolate* isolate) {
2658 if (it->GetRawValue() == isolate->heap()->arguments_marker()) {
2659 if (!it->IsMaterializableByDebugger()) {
2660 return isolate->factory()->undefined_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002661 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002662 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002663 return it->GetValue();
2664}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002665
Ben Murdoch097c5b22016-05-18 11:27:45 +01002666} // namespace
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002667
Ben Murdoch097c5b22016-05-18 11:27:45 +01002668DeoptimizedFrameInfo::DeoptimizedFrameInfo(TranslatedState* state,
2669 TranslatedState::iterator frame_it,
2670 Isolate* isolate) {
2671 // If the previous frame is an adaptor frame, we will take the parameters
2672 // from there.
2673 TranslatedState::iterator parameter_frame = frame_it;
2674 if (parameter_frame != state->begin()) {
2675 parameter_frame--;
2676 }
2677 int parameter_count;
2678 if (parameter_frame->kind() == TranslatedFrame::kArgumentsAdaptor) {
2679 parameter_count = parameter_frame->height() - 1; // Ignore the receiver.
2680 } else {
2681 parameter_frame = frame_it;
2682 parameter_count =
2683 frame_it->shared_info()->internal_formal_parameter_count();
2684 }
2685 TranslatedFrame::iterator parameter_it = parameter_frame->begin();
2686 parameter_it++; // Skip the function.
2687 parameter_it++; // Skip the receiver.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002688
Ben Murdoch097c5b22016-05-18 11:27:45 +01002689 // Figure out whether there is a construct stub frame on top of
2690 // the parameter frame.
2691 has_construct_stub_ =
2692 parameter_frame != state->begin() &&
2693 (parameter_frame - 1)->kind() == TranslatedFrame::kConstructStub;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002694
Ben Murdochc5610432016-08-08 18:44:38 +01002695 source_position_ = Deoptimizer::ComputeSourcePosition(
2696 *frame_it->shared_info(), frame_it->node_id());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002697
2698 TranslatedFrame::iterator value_it = frame_it->begin();
2699 // Get the function. Note that this might materialize the function.
2700 // In case the debugger mutates this value, we should deoptimize
2701 // the function and remember the value in the materialized value store.
2702 function_ = Handle<JSFunction>::cast(value_it->GetValue());
2703
2704 parameters_.resize(static_cast<size_t>(parameter_count));
2705 for (int i = 0; i < parameter_count; i++) {
2706 Handle<Object> parameter = GetValueForDebugger(parameter_it, isolate);
2707 SetParameter(i, parameter);
2708 parameter_it++;
2709 }
2710
2711 // Skip the function, the receiver and the arguments.
2712 int skip_count =
2713 frame_it->shared_info()->internal_formal_parameter_count() + 2;
2714 TranslatedFrame::iterator stack_it = frame_it->begin();
2715 for (int i = 0; i < skip_count; i++) {
2716 stack_it++;
2717 }
2718
2719 // Get the context.
2720 context_ = GetValueForDebugger(stack_it, isolate);
2721 stack_it++;
2722
2723 // Get the expression stack.
2724 int stack_height = frame_it->height();
2725 if (frame_it->kind() == TranslatedFrame::kFunction ||
2726 frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
2727 // For full-code frames, we should not count the context.
2728 // For interpreter frames, we should not count the accumulator.
2729 // TODO(jarin): Clean up the indexing in translated frames.
2730 stack_height--;
2731 }
2732 expression_stack_.resize(static_cast<size_t>(stack_height));
2733 for (int i = 0; i < stack_height; i++) {
2734 Handle<Object> expression = GetValueForDebugger(stack_it, isolate);
2735 SetExpression(i, expression);
2736 stack_it++;
2737 }
2738
2739 // For interpreter frame, skip the accumulator.
2740 if (frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
2741 stack_it++;
2742 }
2743 CHECK(stack_it == frame_it->end());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002744}
2745
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002746
2747const char* Deoptimizer::GetDeoptReason(DeoptReason deopt_reason) {
2748 DCHECK(deopt_reason < kLastDeoptReason);
2749#define DEOPT_MESSAGES_TEXTS(C, T) T,
2750 static const char* deopt_messages_[] = {
2751 DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_TEXTS)};
2752#undef DEOPT_MESSAGES_TEXTS
2753 return deopt_messages_[deopt_reason];
2754}
2755
2756
2757Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code* code, Address pc) {
2758 SourcePosition last_position = SourcePosition::Unknown();
2759 Deoptimizer::DeoptReason last_reason = Deoptimizer::kNoReason;
Ben Murdochc5610432016-08-08 18:44:38 +01002760 int last_deopt_id = Deoptimizer::DeoptInfo::kNoDeoptId;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002761 int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) |
Ben Murdochc5610432016-08-08 18:44:38 +01002762 RelocInfo::ModeMask(RelocInfo::DEOPT_ID) |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002763 RelocInfo::ModeMask(RelocInfo::POSITION);
2764 for (RelocIterator it(code, mask); !it.done(); it.next()) {
2765 RelocInfo* info = it.rinfo();
Ben Murdochc5610432016-08-08 18:44:38 +01002766 if (info->pc() >= pc) {
2767 return DeoptInfo(last_position, last_reason, last_deopt_id);
2768 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002769 if (info->rmode() == RelocInfo::POSITION) {
2770 int raw_position = static_cast<int>(info->data());
2771 last_position = raw_position ? SourcePosition::FromRaw(raw_position)
2772 : SourcePosition::Unknown();
Ben Murdochc5610432016-08-08 18:44:38 +01002773 } else if (info->rmode() == RelocInfo::DEOPT_ID) {
2774 last_deopt_id = static_cast<int>(info->data());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002775 } else if (info->rmode() == RelocInfo::DEOPT_REASON) {
2776 last_reason = static_cast<Deoptimizer::DeoptReason>(info->data());
2777 }
2778 }
Ben Murdochc5610432016-08-08 18:44:38 +01002779 return DeoptInfo(SourcePosition::Unknown(), Deoptimizer::kNoReason, -1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002780}
2781
2782
2783// static
Ben Murdochc5610432016-08-08 18:44:38 +01002784int Deoptimizer::ComputeSourcePosition(SharedFunctionInfo* shared,
2785 BailoutId node_id) {
2786 if (shared->HasBytecodeArray()) {
2787 BytecodeArray* bytecodes = shared->bytecode_array();
2788 // BailoutId points to the next bytecode in the bytecode aray. Subtract
2789 // 1 to get the end of current bytecode.
2790 return bytecodes->SourcePosition(node_id.ToInt() - 1);
2791 } else {
2792 Code* non_optimized_code = shared->code();
2793 FixedArray* raw_data = non_optimized_code->deoptimization_data();
2794 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
2795 unsigned pc_and_state = Deoptimizer::GetOutputInfo(data, node_id, shared);
2796 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
2797 return non_optimized_code->SourcePosition(pc_offset);
2798 }
2799}
2800
2801// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002802TranslatedValue TranslatedValue::NewArgumentsObject(TranslatedState* container,
2803 int length,
2804 int object_index) {
2805 TranslatedValue slot(container, kArgumentsObject);
2806 slot.materialization_info_ = {object_index, length};
2807 return slot;
2808}
2809
2810
2811// static
2812TranslatedValue TranslatedValue::NewDeferredObject(TranslatedState* container,
2813 int length,
2814 int object_index) {
2815 TranslatedValue slot(container, kCapturedObject);
2816 slot.materialization_info_ = {object_index, length};
2817 return slot;
2818}
2819
2820
2821// static
2822TranslatedValue TranslatedValue::NewDuplicateObject(TranslatedState* container,
2823 int id) {
2824 TranslatedValue slot(container, kDuplicatedObject);
2825 slot.materialization_info_ = {id, -1};
2826 return slot;
2827}
2828
2829
2830// static
Ben Murdoch61f157c2016-09-16 13:49:30 +01002831TranslatedValue TranslatedValue::NewFloat(TranslatedState* container,
2832 float value) {
2833 TranslatedValue slot(container, kFloat);
2834 slot.float_value_ = value;
2835 return slot;
2836}
2837
2838// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002839TranslatedValue TranslatedValue::NewDouble(TranslatedState* container,
2840 double value) {
2841 TranslatedValue slot(container, kDouble);
2842 slot.double_value_ = value;
2843 return slot;
2844}
2845
2846
2847// static
2848TranslatedValue TranslatedValue::NewInt32(TranslatedState* container,
2849 int32_t value) {
2850 TranslatedValue slot(container, kInt32);
2851 slot.int32_value_ = value;
2852 return slot;
2853}
2854
2855
2856// static
2857TranslatedValue TranslatedValue::NewUInt32(TranslatedState* container,
2858 uint32_t value) {
2859 TranslatedValue slot(container, kUInt32);
2860 slot.uint32_value_ = value;
2861 return slot;
2862}
2863
2864
2865// static
2866TranslatedValue TranslatedValue::NewBool(TranslatedState* container,
2867 uint32_t value) {
2868 TranslatedValue slot(container, kBoolBit);
2869 slot.uint32_value_ = value;
2870 return slot;
2871}
2872
2873
2874// static
2875TranslatedValue TranslatedValue::NewTagged(TranslatedState* container,
2876 Object* literal) {
2877 TranslatedValue slot(container, kTagged);
2878 slot.raw_literal_ = literal;
2879 return slot;
2880}
2881
2882
2883// static
2884TranslatedValue TranslatedValue::NewInvalid(TranslatedState* container) {
2885 return TranslatedValue(container, kInvalid);
2886}
2887
2888
2889Isolate* TranslatedValue::isolate() const { return container_->isolate(); }
2890
2891
2892Object* TranslatedValue::raw_literal() const {
2893 DCHECK_EQ(kTagged, kind());
2894 return raw_literal_;
2895}
2896
2897
2898int32_t TranslatedValue::int32_value() const {
2899 DCHECK_EQ(kInt32, kind());
2900 return int32_value_;
2901}
2902
2903
2904uint32_t TranslatedValue::uint32_value() const {
2905 DCHECK(kind() == kUInt32 || kind() == kBoolBit);
2906 return uint32_value_;
2907}
2908
Ben Murdoch61f157c2016-09-16 13:49:30 +01002909float TranslatedValue::float_value() const {
2910 DCHECK_EQ(kFloat, kind());
2911 return float_value_;
2912}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002913
2914double TranslatedValue::double_value() const {
2915 DCHECK_EQ(kDouble, kind());
2916 return double_value_;
2917}
2918
2919
2920int TranslatedValue::object_length() const {
2921 DCHECK(kind() == kArgumentsObject || kind() == kCapturedObject);
2922 return materialization_info_.length_;
2923}
2924
2925
2926int TranslatedValue::object_index() const {
2927 DCHECK(kind() == kArgumentsObject || kind() == kCapturedObject ||
2928 kind() == kDuplicatedObject);
2929 return materialization_info_.id_;
2930}
2931
2932
2933Object* TranslatedValue::GetRawValue() const {
2934 // If we have a value, return it.
2935 Handle<Object> result_handle;
2936 if (value_.ToHandle(&result_handle)) {
2937 return *result_handle;
2938 }
2939
2940 // Otherwise, do a best effort to get the value without allocation.
2941 switch (kind()) {
2942 case kTagged:
2943 return raw_literal();
2944
2945 case kInt32: {
2946 bool is_smi = Smi::IsValid(int32_value());
2947 if (is_smi) {
2948 return Smi::FromInt(int32_value());
2949 }
2950 break;
2951 }
2952
2953 case kUInt32: {
2954 bool is_smi = (uint32_value() <= static_cast<uintptr_t>(Smi::kMaxValue));
2955 if (is_smi) {
2956 return Smi::FromInt(static_cast<int32_t>(uint32_value()));
2957 }
2958 break;
2959 }
2960
2961 case kBoolBit: {
2962 if (uint32_value() == 0) {
2963 return isolate()->heap()->false_value();
2964 } else {
2965 CHECK_EQ(1U, uint32_value());
2966 return isolate()->heap()->true_value();
2967 }
2968 }
2969
2970 default:
2971 break;
2972 }
2973
2974 // If we could not get the value without allocation, return the arguments
2975 // marker.
2976 return isolate()->heap()->arguments_marker();
2977}
2978
2979
2980Handle<Object> TranslatedValue::GetValue() {
2981 Handle<Object> result;
2982 // If we already have a value, then get it.
2983 if (value_.ToHandle(&result)) return result;
2984
2985 // Otherwise we have to materialize.
2986 switch (kind()) {
2987 case TranslatedValue::kTagged:
2988 case TranslatedValue::kInt32:
2989 case TranslatedValue::kUInt32:
2990 case TranslatedValue::kBoolBit:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002991 case TranslatedValue::kFloat:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002992 case TranslatedValue::kDouble: {
2993 MaterializeSimple();
2994 return value_.ToHandleChecked();
2995 }
2996
2997 case TranslatedValue::kArgumentsObject:
2998 case TranslatedValue::kCapturedObject:
2999 case TranslatedValue::kDuplicatedObject:
3000 return container_->MaterializeObjectAt(object_index());
3001
3002 case TranslatedValue::kInvalid:
3003 FATAL("unexpected case");
3004 return Handle<Object>::null();
3005 }
3006
3007 FATAL("internal error: value missing");
3008 return Handle<Object>::null();
3009}
3010
3011
3012void TranslatedValue::MaterializeSimple() {
3013 // If we already have materialized, return.
3014 if (!value_.is_null()) return;
3015
3016 Object* raw_value = GetRawValue();
3017 if (raw_value != isolate()->heap()->arguments_marker()) {
3018 // We can get the value without allocation, just return it here.
3019 value_ = Handle<Object>(raw_value, isolate());
3020 return;
3021 }
3022
3023 switch (kind()) {
3024 case kInt32: {
3025 value_ = Handle<Object>(isolate()->factory()->NewNumber(int32_value()));
3026 return;
3027 }
3028
3029 case kUInt32:
3030 value_ = Handle<Object>(isolate()->factory()->NewNumber(uint32_value()));
3031 return;
3032
Ben Murdoch61f157c2016-09-16 13:49:30 +01003033 case kFloat:
3034 value_ = Handle<Object>(isolate()->factory()->NewNumber(float_value()));
3035 return;
3036
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003037 case kDouble:
3038 value_ = Handle<Object>(isolate()->factory()->NewNumber(double_value()));
3039 return;
3040
3041 case kCapturedObject:
3042 case kDuplicatedObject:
3043 case kArgumentsObject:
3044 case kInvalid:
3045 case kTagged:
3046 case kBoolBit:
3047 FATAL("internal error: unexpected materialization.");
3048 break;
3049 }
3050}
3051
3052
3053bool TranslatedValue::IsMaterializedObject() const {
3054 switch (kind()) {
3055 case kCapturedObject:
3056 case kDuplicatedObject:
3057 case kArgumentsObject:
3058 return true;
3059 default:
3060 return false;
3061 }
3062}
3063
Ben Murdoch097c5b22016-05-18 11:27:45 +01003064bool TranslatedValue::IsMaterializableByDebugger() const {
3065 // At the moment, we only allow materialization of doubles.
3066 return (kind() == kDouble);
3067}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003068
3069int TranslatedValue::GetChildrenCount() const {
3070 if (kind() == kCapturedObject || kind() == kArgumentsObject) {
3071 return object_length();
3072 } else {
3073 return 0;
3074 }
3075}
3076
3077
3078uint32_t TranslatedState::GetUInt32Slot(Address fp, int slot_offset) {
3079 Address address = fp + slot_offset;
3080#if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT
3081 return Memory::uint32_at(address + kIntSize);
3082#else
3083 return Memory::uint32_at(address);
3084#endif
3085}
3086
3087
3088void TranslatedValue::Handlify() {
3089 if (kind() == kTagged) {
3090 value_ = Handle<Object>(raw_literal(), isolate());
3091 raw_literal_ = nullptr;
3092 }
3093}
3094
3095
3096TranslatedFrame TranslatedFrame::JSFrame(BailoutId node_id,
3097 SharedFunctionInfo* shared_info,
3098 int height) {
3099 TranslatedFrame frame(kFunction, shared_info->GetIsolate(), shared_info,
3100 height);
3101 frame.node_id_ = node_id;
3102 return frame;
3103}
3104
3105
3106TranslatedFrame TranslatedFrame::InterpretedFrame(
3107 BailoutId bytecode_offset, SharedFunctionInfo* shared_info, int height) {
3108 TranslatedFrame frame(kInterpretedFunction, shared_info->GetIsolate(),
3109 shared_info, height);
3110 frame.node_id_ = bytecode_offset;
3111 return frame;
3112}
3113
3114
3115TranslatedFrame TranslatedFrame::AccessorFrame(
3116 Kind kind, SharedFunctionInfo* shared_info) {
3117 DCHECK(kind == kSetter || kind == kGetter);
3118 return TranslatedFrame(kind, shared_info->GetIsolate(), shared_info);
3119}
3120
3121
3122TranslatedFrame TranslatedFrame::ArgumentsAdaptorFrame(
3123 SharedFunctionInfo* shared_info, int height) {
3124 return TranslatedFrame(kArgumentsAdaptor, shared_info->GetIsolate(),
3125 shared_info, height);
3126}
3127
Ben Murdochda12d292016-06-02 14:46:10 +01003128TranslatedFrame TranslatedFrame::TailCallerFrame(
3129 SharedFunctionInfo* shared_info) {
3130 return TranslatedFrame(kTailCallerFunction, shared_info->GetIsolate(),
3131 shared_info, 0);
3132}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003133
3134TranslatedFrame TranslatedFrame::ConstructStubFrame(
3135 SharedFunctionInfo* shared_info, int height) {
3136 return TranslatedFrame(kConstructStub, shared_info->GetIsolate(), shared_info,
3137 height);
3138}
3139
3140
3141int TranslatedFrame::GetValueCount() {
3142 switch (kind()) {
3143 case kFunction: {
3144 int parameter_count =
3145 raw_shared_info_->internal_formal_parameter_count() + 1;
3146 // + 1 for function.
3147 return height_ + parameter_count + 1;
3148 }
3149
3150 case kInterpretedFunction: {
3151 int parameter_count =
3152 raw_shared_info_->internal_formal_parameter_count() + 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +01003153 // + 2 for function and context.
3154 return height_ + parameter_count + 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003155 }
3156
3157 case kGetter:
3158 return 2; // Function and receiver.
3159
3160 case kSetter:
3161 return 3; // Function, receiver and the value to set.
3162
3163 case kArgumentsAdaptor:
3164 case kConstructStub:
3165 return 1 + height_;
3166
Ben Murdochda12d292016-06-02 14:46:10 +01003167 case kTailCallerFunction:
3168 return 1; // Function.
3169
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003170 case kCompiledStub:
3171 return height_;
3172
3173 case kInvalid:
3174 UNREACHABLE();
3175 break;
3176 }
3177 UNREACHABLE();
3178 return -1;
3179}
3180
3181
3182void TranslatedFrame::Handlify() {
3183 if (raw_shared_info_ != nullptr) {
3184 shared_info_ = Handle<SharedFunctionInfo>(raw_shared_info_);
3185 raw_shared_info_ = nullptr;
3186 }
3187 for (auto& value : values_) {
3188 value.Handlify();
3189 }
3190}
3191
3192
3193TranslatedFrame TranslatedState::CreateNextTranslatedFrame(
3194 TranslationIterator* iterator, FixedArray* literal_array, Address fp,
3195 FILE* trace_file) {
3196 Translation::Opcode opcode =
3197 static_cast<Translation::Opcode>(iterator->Next());
3198 switch (opcode) {
3199 case Translation::JS_FRAME: {
3200 BailoutId node_id = BailoutId(iterator->Next());
3201 SharedFunctionInfo* shared_info =
3202 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3203 int height = iterator->Next();
3204 if (trace_file != nullptr) {
3205 base::SmartArrayPointer<char> name =
3206 shared_info->DebugName()->ToCString();
3207 PrintF(trace_file, " reading input frame %s", name.get());
3208 int arg_count = shared_info->internal_formal_parameter_count() + 1;
3209 PrintF(trace_file, " => node=%d, args=%d, height=%d; inputs:\n",
3210 node_id.ToInt(), arg_count, height);
3211 }
3212 return TranslatedFrame::JSFrame(node_id, shared_info, height);
3213 }
3214
3215 case Translation::INTERPRETED_FRAME: {
3216 BailoutId bytecode_offset = BailoutId(iterator->Next());
3217 SharedFunctionInfo* shared_info =
3218 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3219 int height = iterator->Next();
3220 if (trace_file != nullptr) {
3221 base::SmartArrayPointer<char> name =
3222 shared_info->DebugName()->ToCString();
3223 PrintF(trace_file, " reading input frame %s", name.get());
3224 int arg_count = shared_info->internal_formal_parameter_count() + 1;
3225 PrintF(trace_file,
3226 " => bytecode_offset=%d, args=%d, height=%d; inputs:\n",
3227 bytecode_offset.ToInt(), arg_count, height);
3228 }
3229 return TranslatedFrame::InterpretedFrame(bytecode_offset, shared_info,
3230 height);
3231 }
3232
3233 case Translation::ARGUMENTS_ADAPTOR_FRAME: {
3234 SharedFunctionInfo* shared_info =
3235 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3236 int height = iterator->Next();
3237 if (trace_file != nullptr) {
3238 base::SmartArrayPointer<char> name =
3239 shared_info->DebugName()->ToCString();
3240 PrintF(trace_file, " reading arguments adaptor frame %s", name.get());
3241 PrintF(trace_file, " => height=%d; inputs:\n", height);
3242 }
3243 return TranslatedFrame::ArgumentsAdaptorFrame(shared_info, height);
3244 }
3245
Ben Murdochda12d292016-06-02 14:46:10 +01003246 case Translation::TAIL_CALLER_FRAME: {
3247 SharedFunctionInfo* shared_info =
3248 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3249 if (trace_file != nullptr) {
3250 base::SmartArrayPointer<char> name =
3251 shared_info->DebugName()->ToCString();
3252 PrintF(trace_file, " reading tail caller frame marker %s\n",
3253 name.get());
3254 }
3255 return TranslatedFrame::TailCallerFrame(shared_info);
3256 }
3257
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003258 case Translation::CONSTRUCT_STUB_FRAME: {
3259 SharedFunctionInfo* shared_info =
3260 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3261 int height = iterator->Next();
3262 if (trace_file != nullptr) {
3263 base::SmartArrayPointer<char> name =
3264 shared_info->DebugName()->ToCString();
3265 PrintF(trace_file, " reading construct stub frame %s", name.get());
3266 PrintF(trace_file, " => height=%d; inputs:\n", height);
3267 }
3268 return TranslatedFrame::ConstructStubFrame(shared_info, height);
3269 }
3270
3271 case Translation::GETTER_STUB_FRAME: {
3272 SharedFunctionInfo* shared_info =
3273 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3274 if (trace_file != nullptr) {
3275 base::SmartArrayPointer<char> name =
3276 shared_info->DebugName()->ToCString();
3277 PrintF(trace_file, " reading getter frame %s; inputs:\n", name.get());
3278 }
3279 return TranslatedFrame::AccessorFrame(TranslatedFrame::kGetter,
3280 shared_info);
3281 }
3282
3283 case Translation::SETTER_STUB_FRAME: {
3284 SharedFunctionInfo* shared_info =
3285 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3286 if (trace_file != nullptr) {
3287 base::SmartArrayPointer<char> name =
3288 shared_info->DebugName()->ToCString();
3289 PrintF(trace_file, " reading setter frame %s; inputs:\n", name.get());
3290 }
3291 return TranslatedFrame::AccessorFrame(TranslatedFrame::kSetter,
3292 shared_info);
3293 }
3294
3295 case Translation::COMPILED_STUB_FRAME: {
3296 int height = iterator->Next();
3297 if (trace_file != nullptr) {
3298 PrintF(trace_file,
3299 " reading compiler stub frame => height=%d; inputs:\n", height);
3300 }
3301 return TranslatedFrame::CompiledStubFrame(height,
3302 literal_array->GetIsolate());
3303 }
3304
3305 case Translation::BEGIN:
3306 case Translation::DUPLICATED_OBJECT:
3307 case Translation::ARGUMENTS_OBJECT:
3308 case Translation::CAPTURED_OBJECT:
3309 case Translation::REGISTER:
3310 case Translation::INT32_REGISTER:
3311 case Translation::UINT32_REGISTER:
3312 case Translation::BOOL_REGISTER:
Ben Murdoch61f157c2016-09-16 13:49:30 +01003313 case Translation::FLOAT_REGISTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003314 case Translation::DOUBLE_REGISTER:
3315 case Translation::STACK_SLOT:
3316 case Translation::INT32_STACK_SLOT:
3317 case Translation::UINT32_STACK_SLOT:
3318 case Translation::BOOL_STACK_SLOT:
Ben Murdoch61f157c2016-09-16 13:49:30 +01003319 case Translation::FLOAT_STACK_SLOT:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003320 case Translation::DOUBLE_STACK_SLOT:
3321 case Translation::LITERAL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003322 break;
3323 }
3324 FATAL("We should never get here - unexpected deopt info.");
3325 return TranslatedFrame::InvalidFrame();
3326}
3327
3328
3329// static
3330void TranslatedFrame::AdvanceIterator(
3331 std::deque<TranslatedValue>::iterator* iter) {
3332 int values_to_skip = 1;
3333 while (values_to_skip > 0) {
3334 // Consume the current element.
3335 values_to_skip--;
3336 // Add all the children.
3337 values_to_skip += (*iter)->GetChildrenCount();
3338
3339 (*iter)++;
3340 }
3341}
3342
3343
3344// We can't intermix stack decoding and allocations because
3345// deoptimization infrastracture is not GC safe.
3346// Thus we build a temporary structure in malloced space.
3347TranslatedValue TranslatedState::CreateNextTranslatedValue(
3348 int frame_index, int value_index, TranslationIterator* iterator,
3349 FixedArray* literal_array, Address fp, RegisterValues* registers,
3350 FILE* trace_file) {
3351 disasm::NameConverter converter;
3352
3353 Translation::Opcode opcode =
3354 static_cast<Translation::Opcode>(iterator->Next());
3355 switch (opcode) {
3356 case Translation::BEGIN:
3357 case Translation::JS_FRAME:
3358 case Translation::INTERPRETED_FRAME:
3359 case Translation::ARGUMENTS_ADAPTOR_FRAME:
Ben Murdochda12d292016-06-02 14:46:10 +01003360 case Translation::TAIL_CALLER_FRAME:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003361 case Translation::CONSTRUCT_STUB_FRAME:
3362 case Translation::GETTER_STUB_FRAME:
3363 case Translation::SETTER_STUB_FRAME:
3364 case Translation::COMPILED_STUB_FRAME:
3365 // Peeled off before getting here.
3366 break;
3367
3368 case Translation::DUPLICATED_OBJECT: {
3369 int object_id = iterator->Next();
3370 if (trace_file != nullptr) {
3371 PrintF(trace_file, "duplicated object #%d", object_id);
3372 }
3373 object_positions_.push_back(object_positions_[object_id]);
3374 return TranslatedValue::NewDuplicateObject(this, object_id);
3375 }
3376
3377 case Translation::ARGUMENTS_OBJECT: {
3378 int arg_count = iterator->Next();
3379 int object_index = static_cast<int>(object_positions_.size());
3380 if (trace_file != nullptr) {
3381 PrintF(trace_file, "argumets object #%d (length = %d)", object_index,
3382 arg_count);
3383 }
3384 object_positions_.push_back({frame_index, value_index});
3385 return TranslatedValue::NewArgumentsObject(this, arg_count, object_index);
3386 }
3387
3388 case Translation::CAPTURED_OBJECT: {
3389 int field_count = iterator->Next();
3390 int object_index = static_cast<int>(object_positions_.size());
3391 if (trace_file != nullptr) {
3392 PrintF(trace_file, "captured object #%d (length = %d)", object_index,
3393 field_count);
3394 }
3395 object_positions_.push_back({frame_index, value_index});
3396 return TranslatedValue::NewDeferredObject(this, field_count,
3397 object_index);
3398 }
3399
3400 case Translation::REGISTER: {
3401 int input_reg = iterator->Next();
3402 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3403 intptr_t value = registers->GetRegister(input_reg);
3404 if (trace_file != nullptr) {
3405 PrintF(trace_file, "0x%08" V8PRIxPTR " ; %s ", value,
3406 converter.NameOfCPURegister(input_reg));
3407 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3408 }
3409 return TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value));
3410 }
3411
3412 case Translation::INT32_REGISTER: {
3413 int input_reg = iterator->Next();
3414 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3415 intptr_t value = registers->GetRegister(input_reg);
3416 if (trace_file != nullptr) {
3417 PrintF(trace_file, "%" V8PRIdPTR " ; %s ", value,
3418 converter.NameOfCPURegister(input_reg));
3419 }
3420 return TranslatedValue::NewInt32(this, static_cast<int32_t>(value));
3421 }
3422
3423 case Translation::UINT32_REGISTER: {
3424 int input_reg = iterator->Next();
3425 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3426 intptr_t value = registers->GetRegister(input_reg);
3427 if (trace_file != nullptr) {
3428 PrintF(trace_file, "%" V8PRIuPTR " ; %s (uint)", value,
3429 converter.NameOfCPURegister(input_reg));
3430 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3431 }
3432 return TranslatedValue::NewUInt32(this, static_cast<uint32_t>(value));
3433 }
3434
3435 case Translation::BOOL_REGISTER: {
3436 int input_reg = iterator->Next();
3437 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3438 intptr_t value = registers->GetRegister(input_reg);
3439 if (trace_file != nullptr) {
3440 PrintF(trace_file, "%" V8PRIdPTR " ; %s (bool)", value,
3441 converter.NameOfCPURegister(input_reg));
3442 }
3443 return TranslatedValue::NewBool(this, static_cast<uint32_t>(value));
3444 }
3445
Ben Murdoch61f157c2016-09-16 13:49:30 +01003446 case Translation::FLOAT_REGISTER: {
3447 int input_reg = iterator->Next();
3448 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3449 float value = registers->GetFloatRegister(input_reg);
3450 if (trace_file != nullptr) {
3451 PrintF(trace_file, "%e ; %s (float)", value,
3452 RegisterConfiguration::Crankshaft()->GetFloatRegisterName(
3453 input_reg));
3454 }
3455 return TranslatedValue::NewFloat(this, value);
3456 }
3457
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003458 case Translation::DOUBLE_REGISTER: {
3459 int input_reg = iterator->Next();
3460 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3461 double value = registers->GetDoubleRegister(input_reg);
3462 if (trace_file != nullptr) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01003463 PrintF(trace_file, "%e ; %s (double)", value,
3464 RegisterConfiguration::Crankshaft()->GetDoubleRegisterName(
3465 input_reg));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003466 }
3467 return TranslatedValue::NewDouble(this, value);
3468 }
3469
3470 case Translation::STACK_SLOT: {
3471 int slot_offset =
3472 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3473 intptr_t value = *(reinterpret_cast<intptr_t*>(fp + slot_offset));
3474 if (trace_file != nullptr) {
3475 PrintF(trace_file, "0x%08" V8PRIxPTR " ; [fp %c %d] ", value,
3476 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3477 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3478 }
3479 return TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value));
3480 }
3481
3482 case Translation::INT32_STACK_SLOT: {
3483 int slot_offset =
3484 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3485 uint32_t value = GetUInt32Slot(fp, slot_offset);
3486 if (trace_file != nullptr) {
3487 PrintF(trace_file, "%d ; (int) [fp %c %d] ",
3488 static_cast<int32_t>(value), slot_offset < 0 ? '-' : '+',
3489 std::abs(slot_offset));
3490 }
3491 return TranslatedValue::NewInt32(this, value);
3492 }
3493
3494 case Translation::UINT32_STACK_SLOT: {
3495 int slot_offset =
3496 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3497 uint32_t value = GetUInt32Slot(fp, slot_offset);
3498 if (trace_file != nullptr) {
3499 PrintF(trace_file, "%u ; (uint) [fp %c %d] ", value,
3500 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3501 }
3502 return TranslatedValue::NewUInt32(this, value);
3503 }
3504
3505 case Translation::BOOL_STACK_SLOT: {
3506 int slot_offset =
3507 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3508 uint32_t value = GetUInt32Slot(fp, slot_offset);
3509 if (trace_file != nullptr) {
3510 PrintF(trace_file, "%u ; (bool) [fp %c %d] ", value,
3511 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3512 }
3513 return TranslatedValue::NewBool(this, value);
3514 }
3515
Ben Murdoch61f157c2016-09-16 13:49:30 +01003516 case Translation::FLOAT_STACK_SLOT: {
3517 int slot_offset =
3518 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3519 float value = ReadFloatValue(fp + slot_offset);
3520 if (trace_file != nullptr) {
3521 PrintF(trace_file, "%e ; (float) [fp %c %d] ", value,
3522 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3523 }
3524 return TranslatedValue::NewFloat(this, value);
3525 }
3526
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003527 case Translation::DOUBLE_STACK_SLOT: {
3528 int slot_offset =
3529 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3530 double value = ReadDoubleValue(fp + slot_offset);
3531 if (trace_file != nullptr) {
3532 PrintF(trace_file, "%e ; (double) [fp %c %d] ", value,
3533 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3534 }
3535 return TranslatedValue::NewDouble(this, value);
3536 }
3537
3538 case Translation::LITERAL: {
3539 int literal_index = iterator->Next();
3540 Object* value = literal_array->get(literal_index);
3541 if (trace_file != nullptr) {
3542 PrintF(trace_file, "0x%08" V8PRIxPTR " ; (literal %d) ",
3543 reinterpret_cast<intptr_t>(value), literal_index);
3544 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3545 }
3546
3547 return TranslatedValue::NewTagged(this, value);
3548 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003549 }
3550
3551 FATAL("We should never get here - unexpected deopt info.");
3552 return TranslatedValue(nullptr, TranslatedValue::kInvalid);
3553}
3554
3555
3556TranslatedState::TranslatedState(JavaScriptFrame* frame)
3557 : isolate_(nullptr),
3558 stack_frame_pointer_(nullptr),
3559 has_adapted_arguments_(false) {
3560 int deopt_index = Safepoint::kNoDeoptimizationIndex;
3561 DeoptimizationInputData* data =
3562 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
Ben Murdochc5610432016-08-08 18:44:38 +01003563 DCHECK(data != nullptr && deopt_index != Safepoint::kNoDeoptimizationIndex);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003564 TranslationIterator it(data->TranslationByteArray(),
3565 data->TranslationIndex(deopt_index)->value());
3566 Init(frame->fp(), &it, data->LiteralArray(), nullptr /* registers */,
3567 nullptr /* trace file */);
3568}
3569
3570
3571TranslatedState::TranslatedState()
3572 : isolate_(nullptr),
3573 stack_frame_pointer_(nullptr),
3574 has_adapted_arguments_(false) {}
3575
3576
3577void TranslatedState::Init(Address input_frame_pointer,
3578 TranslationIterator* iterator,
3579 FixedArray* literal_array, RegisterValues* registers,
3580 FILE* trace_file) {
3581 DCHECK(frames_.empty());
3582
3583 isolate_ = literal_array->GetIsolate();
3584 // Read out the 'header' translation.
3585 Translation::Opcode opcode =
3586 static_cast<Translation::Opcode>(iterator->Next());
3587 CHECK(opcode == Translation::BEGIN);
3588
3589 int count = iterator->Next();
3590 iterator->Next(); // Drop JS frames count.
3591
3592 frames_.reserve(count);
3593
3594 std::stack<int> nested_counts;
3595
3596 // Read the frames
3597 for (int i = 0; i < count; i++) {
3598 // Read the frame descriptor.
3599 frames_.push_back(CreateNextTranslatedFrame(
3600 iterator, literal_array, input_frame_pointer, trace_file));
3601 TranslatedFrame& frame = frames_.back();
3602
3603 // Read the values.
3604 int values_to_process = frame.GetValueCount();
3605 while (values_to_process > 0 || !nested_counts.empty()) {
3606 if (trace_file != nullptr) {
3607 if (nested_counts.empty()) {
3608 // For top level values, print the value number.
3609 PrintF(trace_file, " %3i: ",
3610 frame.GetValueCount() - values_to_process);
3611 } else {
3612 // Take care of indenting for nested values.
3613 PrintF(trace_file, " ");
3614 for (size_t j = 0; j < nested_counts.size(); j++) {
3615 PrintF(trace_file, " ");
3616 }
3617 }
3618 }
3619
3620 TranslatedValue value = CreateNextTranslatedValue(
3621 i, static_cast<int>(frame.values_.size()), iterator, literal_array,
3622 input_frame_pointer, registers, trace_file);
3623 frame.Add(value);
3624
3625 if (trace_file != nullptr) {
3626 PrintF(trace_file, "\n");
3627 }
3628
3629 // Update the value count and resolve the nesting.
3630 values_to_process--;
3631 int children_count = value.GetChildrenCount();
3632 if (children_count > 0) {
3633 nested_counts.push(values_to_process);
3634 values_to_process = children_count;
3635 } else {
3636 while (values_to_process == 0 && !nested_counts.empty()) {
3637 values_to_process = nested_counts.top();
3638 nested_counts.pop();
3639 }
3640 }
3641 }
3642 }
3643
3644 CHECK(!iterator->HasNext() ||
3645 static_cast<Translation::Opcode>(iterator->Next()) ==
3646 Translation::BEGIN);
3647}
3648
3649
3650void TranslatedState::Prepare(bool has_adapted_arguments,
3651 Address stack_frame_pointer) {
3652 for (auto& frame : frames_) frame.Handlify();
3653
3654 stack_frame_pointer_ = stack_frame_pointer;
3655 has_adapted_arguments_ = has_adapted_arguments;
3656
3657 UpdateFromPreviouslyMaterializedObjects();
3658}
3659
3660
3661Handle<Object> TranslatedState::MaterializeAt(int frame_index,
3662 int* value_index) {
3663 TranslatedFrame* frame = &(frames_[frame_index]);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003664 CHECK(static_cast<size_t>(*value_index) < frame->values_.size());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003665
3666 TranslatedValue* slot = &(frame->values_[*value_index]);
3667 (*value_index)++;
3668
3669 switch (slot->kind()) {
3670 case TranslatedValue::kTagged:
3671 case TranslatedValue::kInt32:
3672 case TranslatedValue::kUInt32:
3673 case TranslatedValue::kBoolBit:
Ben Murdoch61f157c2016-09-16 13:49:30 +01003674 case TranslatedValue::kFloat:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003675 case TranslatedValue::kDouble: {
3676 slot->MaterializeSimple();
3677 Handle<Object> value = slot->GetValue();
3678 if (value->IsMutableHeapNumber()) {
3679 HeapNumber::cast(*value)->set_map(isolate()->heap()->heap_number_map());
3680 }
3681 return value;
3682 }
3683
3684 case TranslatedValue::kArgumentsObject: {
3685 int length = slot->GetChildrenCount();
3686 Handle<JSObject> arguments;
3687 if (GetAdaptedArguments(&arguments, frame_index)) {
3688 // Store the materialized object and consume the nested values.
3689 for (int i = 0; i < length; ++i) {
3690 MaterializeAt(frame_index, value_index);
3691 }
3692 } else {
3693 Handle<JSFunction> function =
3694 Handle<JSFunction>::cast(frame->front().GetValue());
3695 arguments = isolate_->factory()->NewArgumentsObject(function, length);
3696 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
3697 DCHECK_EQ(array->length(), length);
3698 arguments->set_elements(*array);
3699 for (int i = 0; i < length; ++i) {
3700 Handle<Object> value = MaterializeAt(frame_index, value_index);
3701 array->set(i, *value);
3702 }
3703 }
3704 slot->value_ = arguments;
3705 return arguments;
3706 }
3707 case TranslatedValue::kCapturedObject: {
3708 int length = slot->GetChildrenCount();
3709
3710 // The map must be a tagged object.
3711 CHECK(frame->values_[*value_index].kind() == TranslatedValue::kTagged);
3712
3713 Handle<Object> result;
3714 if (slot->value_.ToHandle(&result)) {
3715 // This has been previously materialized, return the previous value.
3716 // We still need to skip all the nested objects.
3717 for (int i = 0; i < length; i++) {
3718 MaterializeAt(frame_index, value_index);
3719 }
3720
3721 return result;
3722 }
3723
3724 Handle<Object> map_object = MaterializeAt(frame_index, value_index);
3725 Handle<Map> map =
3726 Map::GeneralizeAllFieldRepresentations(Handle<Map>::cast(map_object));
3727 switch (map->instance_type()) {
3728 case MUTABLE_HEAP_NUMBER_TYPE:
3729 case HEAP_NUMBER_TYPE: {
3730 // Reuse the HeapNumber value directly as it is already properly
3731 // tagged and skip materializing the HeapNumber explicitly.
3732 Handle<Object> object = MaterializeAt(frame_index, value_index);
3733 slot->value_ = object;
3734 // On 32-bit architectures, there is an extra slot there because
3735 // the escape analysis calculates the number of slots as
3736 // object-size/pointer-size. To account for this, we read out
3737 // any extra slots.
3738 for (int i = 0; i < length - 2; i++) {
3739 MaterializeAt(frame_index, value_index);
3740 }
3741 return object;
3742 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01003743 case JS_OBJECT_TYPE:
3744 case JS_ERROR_TYPE:
3745 case JS_ARGUMENTS_TYPE: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003746 Handle<JSObject> object =
3747 isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED);
3748 slot->value_ = object;
3749 Handle<Object> properties = MaterializeAt(frame_index, value_index);
3750 Handle<Object> elements = MaterializeAt(frame_index, value_index);
3751 object->set_properties(FixedArray::cast(*properties));
3752 object->set_elements(FixedArrayBase::cast(*elements));
3753 for (int i = 0; i < length - 3; ++i) {
3754 Handle<Object> value = MaterializeAt(frame_index, value_index);
3755 FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
3756 object->FastPropertyAtPut(index, *value);
3757 }
3758 return object;
3759 }
3760 case JS_ARRAY_TYPE: {
3761 Handle<JSArray> object =
3762 isolate_->factory()->NewJSArray(0, map->elements_kind());
3763 slot->value_ = object;
3764 Handle<Object> properties = MaterializeAt(frame_index, value_index);
3765 Handle<Object> elements = MaterializeAt(frame_index, value_index);
3766 Handle<Object> length = MaterializeAt(frame_index, value_index);
3767 object->set_properties(FixedArray::cast(*properties));
3768 object->set_elements(FixedArrayBase::cast(*elements));
3769 object->set_length(*length);
3770 return object;
3771 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01003772 case JS_FUNCTION_TYPE: {
3773 Handle<JSFunction> object =
3774 isolate_->factory()->NewFunctionFromSharedFunctionInfo(
3775 handle(isolate_->object_function()->shared()),
3776 handle(isolate_->context()));
3777 slot->value_ = object;
3778 // We temporarily allocated a JSFunction for the {Object} function
3779 // within the current context, to break cycles in the object graph.
3780 // The correct function and context will be set below once available.
3781 Handle<Object> properties = MaterializeAt(frame_index, value_index);
3782 Handle<Object> elements = MaterializeAt(frame_index, value_index);
3783 Handle<Object> prototype = MaterializeAt(frame_index, value_index);
3784 Handle<Object> shared = MaterializeAt(frame_index, value_index);
3785 Handle<Object> context = MaterializeAt(frame_index, value_index);
3786 Handle<Object> literals = MaterializeAt(frame_index, value_index);
3787 Handle<Object> entry = MaterializeAt(frame_index, value_index);
3788 Handle<Object> next_link = MaterializeAt(frame_index, value_index);
3789 object->ReplaceCode(*isolate_->builtins()->CompileLazy());
3790 object->set_map(*map);
3791 object->set_properties(FixedArray::cast(*properties));
3792 object->set_elements(FixedArrayBase::cast(*elements));
3793 object->set_prototype_or_initial_map(*prototype);
3794 object->set_shared(SharedFunctionInfo::cast(*shared));
3795 object->set_context(Context::cast(*context));
3796 object->set_literals(LiteralsArray::cast(*literals));
3797 CHECK(entry->IsNumber()); // Entry to compile lazy stub.
3798 CHECK(next_link->IsUndefined(isolate_));
3799 return object;
3800 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003801 case FIXED_ARRAY_TYPE: {
3802 Handle<Object> lengthObject = MaterializeAt(frame_index, value_index);
3803 int32_t length = 0;
3804 CHECK(lengthObject->ToInt32(&length));
3805 Handle<FixedArray> object =
3806 isolate_->factory()->NewFixedArray(length);
3807 // We need to set the map, because the fixed array we are
3808 // materializing could be a context or an arguments object,
3809 // in which case we must retain that information.
3810 object->set_map(*map);
3811 slot->value_ = object;
3812 for (int i = 0; i < length; ++i) {
3813 Handle<Object> value = MaterializeAt(frame_index, value_index);
3814 object->set(i, *value);
3815 }
3816 return object;
3817 }
3818 case FIXED_DOUBLE_ARRAY_TYPE: {
3819 DCHECK_EQ(*map, isolate_->heap()->fixed_double_array_map());
3820 Handle<Object> lengthObject = MaterializeAt(frame_index, value_index);
3821 int32_t length = 0;
3822 CHECK(lengthObject->ToInt32(&length));
3823 Handle<FixedArrayBase> object =
3824 isolate_->factory()->NewFixedDoubleArray(length);
3825 slot->value_ = object;
3826 if (length > 0) {
3827 Handle<FixedDoubleArray> double_array =
3828 Handle<FixedDoubleArray>::cast(object);
3829 for (int i = 0; i < length; ++i) {
3830 Handle<Object> value = MaterializeAt(frame_index, value_index);
3831 CHECK(value->IsNumber());
3832 double_array->set(i, value->Number());
3833 }
3834 }
3835 return object;
3836 }
3837 default:
3838 PrintF(stderr, "[couldn't handle instance type %d]\n",
3839 map->instance_type());
3840 FATAL("unreachable");
3841 return Handle<Object>::null();
3842 }
3843 UNREACHABLE();
3844 break;
3845 }
3846
3847 case TranslatedValue::kDuplicatedObject: {
3848 int object_index = slot->object_index();
3849 TranslatedState::ObjectPosition pos = object_positions_[object_index];
3850
3851 // Make sure the duplicate is refering to a previous object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003852 CHECK(pos.frame_index_ < frame_index ||
3853 (pos.frame_index_ == frame_index &&
3854 pos.value_index_ < *value_index - 1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003855
3856 Handle<Object> object =
3857 frames_[pos.frame_index_].values_[pos.value_index_].GetValue();
3858
3859 // The object should have a (non-sentinel) value.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003860 CHECK(!object.is_null() &&
3861 !object.is_identical_to(isolate_->factory()->arguments_marker()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003862
3863 slot->value_ = object;
3864 return object;
3865 }
3866
3867 case TranslatedValue::kInvalid:
3868 UNREACHABLE();
3869 break;
3870 }
3871
3872 FATAL("We should never get here - unexpected deopt slot kind.");
3873 return Handle<Object>::null();
3874}
3875
3876
3877Handle<Object> TranslatedState::MaterializeObjectAt(int object_index) {
3878 TranslatedState::ObjectPosition pos = object_positions_[object_index];
3879 return MaterializeAt(pos.frame_index_, &(pos.value_index_));
3880}
3881
3882
3883bool TranslatedState::GetAdaptedArguments(Handle<JSObject>* result,
3884 int frame_index) {
3885 if (frame_index == 0) {
3886 // Top level frame -> we need to go to the parent frame on the stack.
3887 if (!has_adapted_arguments_) return false;
3888
3889 // This is top level frame, so we need to go to the stack to get
3890 // this function's argument. (Note that this relies on not inlining
3891 // recursive functions!)
3892 Handle<JSFunction> function =
3893 Handle<JSFunction>::cast(frames_[frame_index].front().GetValue());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003894 *result = Accessors::FunctionGetArguments(function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003895 return true;
3896 } else {
3897 TranslatedFrame* previous_frame = &(frames_[frame_index]);
3898 if (previous_frame->kind() != TranslatedFrame::kArgumentsAdaptor) {
3899 return false;
3900 }
3901 // We get the adapted arguments from the parent translation.
3902 int length = previous_frame->height();
3903 Handle<JSFunction> function =
3904 Handle<JSFunction>::cast(previous_frame->front().GetValue());
3905 Handle<JSObject> arguments =
3906 isolate_->factory()->NewArgumentsObject(function, length);
3907 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
3908 arguments->set_elements(*array);
3909 TranslatedFrame::iterator arg_iterator = previous_frame->begin();
3910 arg_iterator++; // Skip function.
3911 for (int i = 0; i < length; ++i) {
3912 Handle<Object> value = arg_iterator->GetValue();
3913 array->set(i, *value);
3914 arg_iterator++;
3915 }
3916 CHECK(arg_iterator == previous_frame->end());
3917 *result = arguments;
3918 return true;
3919 }
3920}
3921
3922
3923TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex(
3924 int jsframe_index, int* args_count) {
3925 for (size_t i = 0; i < frames_.size(); i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003926 if (frames_[i].kind() == TranslatedFrame::kFunction ||
3927 frames_[i].kind() == TranslatedFrame::kInterpretedFunction) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003928 if (jsframe_index > 0) {
3929 jsframe_index--;
3930 } else {
3931 // We have the JS function frame, now check if it has arguments adaptor.
3932 if (i > 0 &&
3933 frames_[i - 1].kind() == TranslatedFrame::kArgumentsAdaptor) {
3934 *args_count = frames_[i - 1].height();
3935 return &(frames_[i - 1]);
3936 }
3937 *args_count =
3938 frames_[i].shared_info()->internal_formal_parameter_count() + 1;
3939 return &(frames_[i]);
3940 }
3941 }
3942 }
3943 return nullptr;
3944}
3945
3946
3947void TranslatedState::StoreMaterializedValuesAndDeopt() {
3948 MaterializedObjectStore* materialized_store =
3949 isolate_->materialized_object_store();
3950 Handle<FixedArray> previously_materialized_objects =
3951 materialized_store->Get(stack_frame_pointer_);
3952
3953 Handle<Object> marker = isolate_->factory()->arguments_marker();
3954
3955 int length = static_cast<int>(object_positions_.size());
3956 bool new_store = false;
3957 if (previously_materialized_objects.is_null()) {
3958 previously_materialized_objects =
3959 isolate_->factory()->NewFixedArray(length);
3960 for (int i = 0; i < length; i++) {
3961 previously_materialized_objects->set(i, *marker);
3962 }
3963 new_store = true;
3964 }
3965
Ben Murdoch097c5b22016-05-18 11:27:45 +01003966 CHECK_EQ(length, previously_materialized_objects->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003967
3968 bool value_changed = false;
3969 for (int i = 0; i < length; i++) {
3970 TranslatedState::ObjectPosition pos = object_positions_[i];
3971 TranslatedValue* value_info =
3972 &(frames_[pos.frame_index_].values_[pos.value_index_]);
3973
Ben Murdoch097c5b22016-05-18 11:27:45 +01003974 CHECK(value_info->IsMaterializedObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003975
3976 Handle<Object> value(value_info->GetRawValue(), isolate_);
3977
3978 if (!value.is_identical_to(marker)) {
3979 if (previously_materialized_objects->get(i) == *marker) {
3980 previously_materialized_objects->set(i, *value);
3981 value_changed = true;
3982 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003983 CHECK(previously_materialized_objects->get(i) == *value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003984 }
3985 }
3986 }
3987 if (new_store && value_changed) {
3988 materialized_store->Set(stack_frame_pointer_,
3989 previously_materialized_objects);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003990 CHECK(frames_[0].kind() == TranslatedFrame::kFunction ||
Ben Murdochda12d292016-06-02 14:46:10 +01003991 frames_[0].kind() == TranslatedFrame::kInterpretedFunction ||
3992 frames_[0].kind() == TranslatedFrame::kTailCallerFunction);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003993 Object* const function = frames_[0].front().GetRawValue();
3994 Deoptimizer::DeoptimizeFunction(JSFunction::cast(function));
3995 }
3996}
3997
3998
3999void TranslatedState::UpdateFromPreviouslyMaterializedObjects() {
4000 MaterializedObjectStore* materialized_store =
4001 isolate_->materialized_object_store();
4002 Handle<FixedArray> previously_materialized_objects =
4003 materialized_store->Get(stack_frame_pointer_);
4004
4005 // If we have no previously materialized objects, there is nothing to do.
4006 if (previously_materialized_objects.is_null()) return;
4007
4008 Handle<Object> marker = isolate_->factory()->arguments_marker();
4009
4010 int length = static_cast<int>(object_positions_.size());
Ben Murdoch097c5b22016-05-18 11:27:45 +01004011 CHECK_EQ(length, previously_materialized_objects->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004012
4013 for (int i = 0; i < length; i++) {
4014 // For a previously materialized objects, inject their value into the
4015 // translated values.
4016 if (previously_materialized_objects->get(i) != *marker) {
4017 TranslatedState::ObjectPosition pos = object_positions_[i];
4018 TranslatedValue* value_info =
4019 &(frames_[pos.frame_index_].values_[pos.value_index_]);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004020 CHECK(value_info->IsMaterializedObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004021
4022 value_info->value_ =
4023 Handle<Object>(previously_materialized_objects->get(i), isolate_);
4024 }
4025 }
4026}
4027
4028} // namespace internal
4029} // namespace v8