blob: adf4cf1296676a73f5e1319b0d14a23e8554d44a [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 Murdoch4a90d5f2016-03-22 12:00:34 +000016#include "src/profiler/cpu-profiler.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010017#include "src/tracing/trace-event.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018#include "src/v8.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010019
20
21namespace v8 {
22namespace internal {
23
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024static MemoryChunk* AllocateCodeChunk(MemoryAllocator* allocator) {
25 return allocator->AllocateChunk(Deoptimizer::GetMaxDeoptTableSize(),
26 base::OS::CommitPageSize(),
27#if defined(__native_client__)
28 // The Native Client port of V8 uses an interpreter,
29 // so code pages don't need PROT_EXEC.
30 NOT_EXECUTABLE,
31#else
32 EXECUTABLE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000033#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034 NULL);
35}
36
37
38DeoptimizerData::DeoptimizerData(MemoryAllocator* allocator)
39 : allocator_(allocator),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040 current_(NULL) {
Ben Murdochda12d292016-06-02 14:46:10 +010041 for (int i = 0; i <= Deoptimizer::kLastBailoutType; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042 deopt_entry_code_entries_[i] = -1;
43 deopt_entry_code_[i] = AllocateCodeChunk(allocator);
44 }
Steve Block44f0eee2011-05-26 01:26:41 +010045}
Ben Murdochb0fe1622011-05-05 13:52:32 +010046
47
Steve Block44f0eee2011-05-26 01:26:41 +010048DeoptimizerData::~DeoptimizerData() {
Ben Murdochda12d292016-06-02 14:46:10 +010049 for (int i = 0; i <= Deoptimizer::kLastBailoutType; ++i) {
Ben Murdochc5610432016-08-08 18:44:38 +010050 allocator_->Free<MemoryAllocator::kFull>(deopt_entry_code_[i]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051 deopt_entry_code_[i] = NULL;
Steve Block44f0eee2011-05-26 01:26:41 +010052 }
53}
54
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000055
Ben Murdochb8a8cc12014-11-26 15:28:44 +000056Code* Deoptimizer::FindDeoptimizingCode(Address addr) {
57 if (function_->IsHeapObject()) {
58 // Search all deoptimizing code in the native context of the function.
59 Context* native_context = function_->context()->native_context();
60 Object* element = native_context->DeoptimizedCodeListHead();
61 while (!element->IsUndefined()) {
62 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();
189 while (!element->IsUndefined()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190 JSFunction* function = JSFunction::cast(element);
191 Object* next = function->next_function_link();
192 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION ||
193 (visitor->VisitFunction(function),
194 function->code()->kind() != Code::OPTIMIZED_FUNCTION)) {
195 // The function no longer refers to optimized code, or the visitor
196 // changed the code to which it refers to no longer be optimized code.
197 // Remove the function from this list.
198 if (prev != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199 prev->set_next_function_link(next, UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200 } else {
201 context->SetOptimizedFunctionsListHead(next);
202 }
203 // The visitor should not alter the link directly.
204 CHECK_EQ(function->next_function_link(), next);
205 // Set the next function link to undefined to indicate it is no longer
206 // in the optimized functions list.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 function->set_next_function_link(context->GetHeap()->undefined_value(),
208 SKIP_WRITE_BARRIER);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209 } else {
210 // The visitor should not alter the link directly.
211 CHECK_EQ(function->next_function_link(), next);
212 // preserve this element.
213 prev = function;
214 }
215 element = next;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100216 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217
Ben Murdochb0fe1622011-05-05 13:52:32 +0100218 visitor->LeaveContext(context);
219}
220
221
Ben Murdochb0fe1622011-05-05 13:52:32 +0100222void Deoptimizer::VisitAllOptimizedFunctions(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000223 Isolate* isolate,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100224 OptimizedFunctionVisitor* visitor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225 DisallowHeapAllocation no_allocation;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100226
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000227 // Run through the list of all native contexts.
228 Object* context = isolate->heap()->native_contexts_list();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100229 while (!context->IsUndefined()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230 VisitAllOptimizedFunctionsForContext(Context::cast(context), visitor);
Ben Murdochc5610432016-08-08 18:44:38 +0100231 context = Context::cast(context)->next_context_link();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100232 }
233}
234
235
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236// Unlink functions referring to code marked for deoptimization, then move
237// marked code from the optimized code list to the deoptimized code list,
238// and patch code for lazy deopt.
239void Deoptimizer::DeoptimizeMarkedCodeForContext(Context* context) {
240 DisallowHeapAllocation no_allocation;
241
242 // A "closure" that unlinks optimized code that is going to be
243 // deoptimized from the functions that refer to it.
244 class SelectedCodeUnlinker: public OptimizedFunctionVisitor {
245 public:
246 virtual void EnterContext(Context* context) { } // Don't care.
247 virtual void LeaveContext(Context* context) { } // Don't care.
248 virtual void VisitFunction(JSFunction* function) {
249 Code* code = function->code();
250 if (!code->marked_for_deoptimization()) return;
251
252 // Unlink this function and evict from optimized code map.
253 SharedFunctionInfo* shared = function->shared();
254 function->set_code(shared->code());
255
256 if (FLAG_trace_deopt) {
257 CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
258 PrintF(scope.file(), "[deoptimizer unlinked: ");
259 function->PrintName(scope.file());
260 PrintF(scope.file(),
261 " / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
262 }
263 }
264 };
265
266 // Unlink all functions that refer to marked code.
267 SelectedCodeUnlinker unlinker;
268 VisitAllOptimizedFunctionsForContext(context, &unlinker);
269
270 Isolate* isolate = context->GetHeap()->isolate();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100271#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272 Code* topmost_optimized_code = NULL;
273 bool safe_to_deopt_topmost_optimized_code = false;
274 // Make sure all activations of optimized code can deopt at their current PC.
275 // The topmost optimized code has special handling because it cannot be
276 // deoptimized due to weak object dependency.
277 for (StackFrameIterator it(isolate, isolate->thread_local_top());
278 !it.done(); it.Advance()) {
279 StackFrame::Type type = it.frame()->type();
280 if (type == StackFrame::OPTIMIZED) {
281 Code* code = it.frame()->LookupCode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000282 JSFunction* function =
283 static_cast<OptimizedFrame*>(it.frame())->function();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284 if (FLAG_trace_deopt) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 CodeTracer::Scope scope(isolate->GetCodeTracer());
286 PrintF(scope.file(), "[deoptimizer found activation of function: ");
287 function->PrintName(scope.file());
288 PrintF(scope.file(),
289 " / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
290 }
291 SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc());
292 int deopt_index = safepoint.deoptimization_index();
293 // Turbofan deopt is checked when we are patching addresses on stack.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000294 bool turbofanned = code->is_turbofanned() &&
295 function->shared()->asm_function() &&
296 !FLAG_turbo_asm_deoptimization;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 bool safe_to_deopt =
298 deopt_index != Safepoint::kNoDeoptimizationIndex || turbofanned;
Ben Murdochc5610432016-08-08 18:44:38 +0100299 bool builtin = code->kind() == Code::BUILTIN;
300 CHECK(topmost_optimized_code == NULL || safe_to_deopt || turbofanned ||
301 builtin);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302 if (topmost_optimized_code == NULL) {
303 topmost_optimized_code = code;
304 safe_to_deopt_topmost_optimized_code = safe_to_deopt;
305 }
306 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100307 }
308#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000309
310 // Move marked code from the optimized code list to the deoptimized
311 // code list, collecting them into a ZoneList.
Ben Murdochda12d292016-06-02 14:46:10 +0100312 Zone zone(isolate->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000313 ZoneList<Code*> codes(10, &zone);
314
315 // Walk over all optimized code objects in this native context.
316 Code* prev = NULL;
317 Object* element = context->OptimizedCodeListHead();
318 while (!element->IsUndefined()) {
319 Code* code = Code::cast(element);
320 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
321 Object* next = code->next_code_link();
322
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000323 if (code->marked_for_deoptimization()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000324 // Put the code into the list for later patching.
325 codes.Add(code, &zone);
326
327 if (prev != NULL) {
328 // Skip this code in the optimized code list.
329 prev->set_next_code_link(next);
330 } else {
331 // There was no previous node, the next node is the new head.
332 context->SetOptimizedCodeListHead(next);
333 }
334
335 // Move the code to the _deoptimized_ code list.
336 code->set_next_code_link(context->DeoptimizedCodeListHead());
337 context->SetDeoptimizedCodeListHead(code);
338 } else {
339 // Not marked; preserve this element.
340 prev = code;
341 }
342 element = next;
343 }
344
Ben Murdoch097c5b22016-05-18 11:27:45 +0100345 // We need a handle scope only because of the macro assembler,
346 // which is used in code patching in EnsureCodeForDeoptimizationEntry.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000347 HandleScope scope(isolate);
348
349 // Now patch all the codes for deoptimization.
350 for (int i = 0; i < codes.length(); i++) {
351#ifdef DEBUG
352 if (codes[i] == topmost_optimized_code) {
353 DCHECK(safe_to_deopt_topmost_optimized_code);
354 }
355#endif
356 // It is finally time to die, code object.
357
358 // Remove the code from optimized code map.
359 DeoptimizationInputData* deopt_data =
360 DeoptimizationInputData::cast(codes[i]->deoptimization_data());
361 SharedFunctionInfo* shared =
362 SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo());
363 shared->EvictFromOptimizedCodeMap(codes[i], "deoptimized code");
364
365 // Do platform-specific patching to force any activations to lazy deopt.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 PatchCodeForDeoptimization(isolate, codes[i]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000367
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000368 // We might be in the middle of incremental marking with compaction.
369 // Tell collector to treat this code object in a special way and
370 // ignore all slots that might have been recorded on it.
371 isolate->heap()->mark_compact_collector()->InvalidateCode(codes[i]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000372 }
373}
374
375
376void Deoptimizer::DeoptimizeAll(Isolate* isolate) {
Ben Murdochc5610432016-08-08 18:44:38 +0100377 RuntimeCallTimerScope runtimeTimer(isolate,
378 &RuntimeCallStats::DeoptimizeCode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100379 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
380 TRACE_EVENT0("v8", "V8.DeoptimizeCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000381 if (FLAG_trace_deopt) {
382 CodeTracer::Scope scope(isolate->GetCodeTracer());
383 PrintF(scope.file(), "[deoptimize all code in all contexts]\n");
384 }
385 DisallowHeapAllocation no_allocation;
386 // For all contexts, mark all code, then deoptimize.
387 Object* context = isolate->heap()->native_contexts_list();
388 while (!context->IsUndefined()) {
389 Context* native_context = Context::cast(context);
390 MarkAllCodeForContext(native_context);
391 DeoptimizeMarkedCodeForContext(native_context);
Ben Murdochc5610432016-08-08 18:44:38 +0100392 context = native_context->next_context_link();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000393 }
394}
395
396
397void Deoptimizer::DeoptimizeMarkedCode(Isolate* isolate) {
Ben Murdochc5610432016-08-08 18:44:38 +0100398 RuntimeCallTimerScope runtimeTimer(isolate,
399 &RuntimeCallStats::DeoptimizeCode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100400 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
401 TRACE_EVENT0("v8", "V8.DeoptimizeCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000402 if (FLAG_trace_deopt) {
403 CodeTracer::Scope scope(isolate->GetCodeTracer());
404 PrintF(scope.file(), "[deoptimize marked code in all contexts]\n");
405 }
406 DisallowHeapAllocation no_allocation;
407 // For all contexts, deoptimize code already marked.
408 Object* context = isolate->heap()->native_contexts_list();
409 while (!context->IsUndefined()) {
410 Context* native_context = Context::cast(context);
411 DeoptimizeMarkedCodeForContext(native_context);
Ben Murdochc5610432016-08-08 18:44:38 +0100412 context = native_context->next_context_link();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413 }
414}
415
416
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000417void Deoptimizer::MarkAllCodeForContext(Context* context) {
418 Object* element = context->OptimizedCodeListHead();
419 while (!element->IsUndefined()) {
420 Code* code = Code::cast(element);
421 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
422 code->set_marked_for_deoptimization(true);
423 element = code->next_code_link();
424 }
425}
426
427
428void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
Ben Murdochc5610432016-08-08 18:44:38 +0100429 Isolate* isolate = function->GetIsolate();
430 RuntimeCallTimerScope runtimeTimer(isolate,
431 &RuntimeCallStats::DeoptimizeCode);
432 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100433 TRACE_EVENT0("v8", "V8.DeoptimizeCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000434 Code* code = function->code();
435 if (code->kind() == Code::OPTIMIZED_FUNCTION) {
436 // Mark the code for deoptimization and unlink any functions that also
437 // refer to that code. The code cannot be shared across native contexts,
438 // so we only need to search one.
439 code->set_marked_for_deoptimization(true);
440 DeoptimizeMarkedCodeForContext(function->context()->native_context());
441 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100442}
443
444
Ben Murdoch8b112d22011-06-08 16:22:53 +0100445void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100446 deoptimizer->DoComputeOutputFrames();
447}
448
449
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000450bool Deoptimizer::TraceEnabledFor(BailoutType deopt_type,
451 StackFrame::Type frame_type) {
452 switch (deopt_type) {
453 case EAGER:
454 case SOFT:
455 case LAZY:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000456 return (frame_type == StackFrame::STUB)
457 ? FLAG_trace_stub_failures
458 : FLAG_trace_deopt;
459 }
460 FATAL("Unsupported deopt type");
461 return false;
462}
463
464
465const char* Deoptimizer::MessageFor(BailoutType type) {
466 switch (type) {
467 case EAGER: return "eager";
468 case SOFT: return "soft";
469 case LAZY: return "lazy";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000470 }
471 FATAL("Unsupported deopt type");
472 return NULL;
473}
474
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function,
476 BailoutType type, unsigned bailout_id, Address from,
477 int fp_to_sp_delta, Code* optimized_code)
Steve Block44f0eee2011-05-26 01:26:41 +0100478 : isolate_(isolate),
479 function_(function),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100480 bailout_id_(bailout_id),
481 bailout_type_(type),
482 from_(from),
483 fp_to_sp_delta_(fp_to_sp_delta),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100484 deoptimizing_throw_(false),
485 catch_handler_data_(-1),
486 catch_handler_pc_offset_(-1),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000487 input_(nullptr),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100488 output_count_(0),
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100489 jsframe_count_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490 output_(nullptr),
Ben Murdochda12d292016-06-02 14:46:10 +0100491 caller_frame_top_(0),
492 caller_fp_(0),
493 caller_pc_(0),
494 caller_constant_pool_(0),
495 input_frame_context_(0),
496 stack_fp_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 trace_scope_(nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100498 if (isolate->deoptimizer_lazy_throw()) {
499 isolate->set_deoptimizer_lazy_throw(false);
500 deoptimizing_throw_ = true;
501 }
502
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503 // For COMPILED_STUBs called from builtins, the function pointer is a SMI
504 // indicating an internal frame.
505 if (function->IsSmi()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000506 function = nullptr;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100507 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000508 DCHECK(from != nullptr);
509 if (function != nullptr && function->IsOptimized()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000510 function->shared()->increment_deopt_count();
511 if (bailout_type_ == Deoptimizer::SOFT) {
512 isolate->counters()->soft_deopts_executed()->Increment();
513 // Soft deopts shouldn't count against the overall re-optimization count
514 // that can eventually lead to disabling optimization for a function.
515 int opt_count = function->shared()->opt_count();
516 if (opt_count > 0) opt_count--;
517 function->shared()->set_opt_count(opt_count);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100518 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100519 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520 compiled_code_ = FindOptimizedCode(function, optimized_code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000521#if DEBUG
522 DCHECK(compiled_code_ != NULL);
523 if (type == EAGER || type == SOFT || type == LAZY) {
524 DCHECK(compiled_code_->kind() != Code::FUNCTION);
525 }
526#endif
527
528 StackFrame::Type frame_type = function == NULL
529 ? StackFrame::STUB
530 : StackFrame::JAVA_SCRIPT;
531 trace_scope_ = TraceEnabledFor(type, frame_type) ?
532 new CodeTracer::Scope(isolate->GetCodeTracer()) : NULL;
533#ifdef DEBUG
534 CHECK(AllowHeapAllocation::IsAllowed());
535 disallow_heap_allocation_ = new DisallowHeapAllocation();
536#endif // DEBUG
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000537 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
538 PROFILE(isolate_, CodeDeoptEvent(compiled_code_, from_, fp_to_sp_delta_));
539 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100540 unsigned size = ComputeInputFrameSize();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100541 int parameter_count =
542 function == nullptr
543 ? 0
544 : (function->shared()->internal_formal_parameter_count() + 1);
545 input_ = new (size) FrameDescription(size, parameter_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000546 input_->SetFrameType(frame_type);
547}
548
549
550Code* Deoptimizer::FindOptimizedCode(JSFunction* function,
551 Code* optimized_code) {
552 switch (bailout_type_) {
553 case Deoptimizer::SOFT:
554 case Deoptimizer::EAGER:
555 case Deoptimizer::LAZY: {
556 Code* compiled_code = FindDeoptimizingCode(from_);
557 return (compiled_code == NULL)
558 ? static_cast<Code*>(isolate_->FindCodeObject(from_))
559 : compiled_code;
560 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000561 }
562 FATAL("Could not find code for optimized function");
563 return NULL;
564}
565
566
567void Deoptimizer::PrintFunctionName() {
568 if (function_->IsJSFunction()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400569 function_->ShortPrint(trace_scope_->file());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000570 } else {
571 PrintF(trace_scope_->file(),
572 "%s", Code::Kind2String(compiled_code_->kind()));
573 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100574}
575
576
577Deoptimizer::~Deoptimizer() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000578 DCHECK(input_ == NULL && output_ == NULL);
579 DCHECK(disallow_heap_allocation_ == NULL);
580 delete trace_scope_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100581}
582
583
584void Deoptimizer::DeleteFrameDescriptions() {
585 delete input_;
586 for (int i = 0; i < output_count_; ++i) {
587 if (output_[i] != input_) delete output_[i];
588 }
589 delete[] output_;
590 input_ = NULL;
591 output_ = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592#ifdef DEBUG
593 CHECK(!AllowHeapAllocation::IsAllowed());
594 CHECK(disallow_heap_allocation_ != NULL);
595 delete disallow_heap_allocation_;
596 disallow_heap_allocation_ = NULL;
597#endif // DEBUG
Ben Murdochb0fe1622011-05-05 13:52:32 +0100598}
599
600
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate,
602 int id,
603 BailoutType type,
604 GetEntryMode mode) {
605 CHECK_GE(id, 0);
606 if (id >= kMaxNumberOfEntries) return NULL;
607 if (mode == ENSURE_ENTRY_CODE) {
608 EnsureCodeForDeoptimizationEntry(isolate, type, id);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100609 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000610 CHECK_EQ(mode, CALCULATE_ENTRY_ADDRESS);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100611 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000612 DeoptimizerData* data = isolate->deoptimizer_data();
Ben Murdochda12d292016-06-02 14:46:10 +0100613 CHECK_LE(type, kLastBailoutType);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000614 MemoryChunk* base = data->deopt_entry_code_[type];
615 return base->area_start() + (id * table_entry_size_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100616}
617
618
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000619int Deoptimizer::GetDeoptimizationId(Isolate* isolate,
620 Address addr,
621 BailoutType type) {
622 DeoptimizerData* data = isolate->deoptimizer_data();
623 MemoryChunk* base = data->deopt_entry_code_[type];
624 Address start = base->area_start();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400625 if (addr < start ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000626 addr >= start + (kMaxNumberOfEntries * table_entry_size_)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100627 return kNotDeoptimizationEntry;
628 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 DCHECK_EQ(0,
630 static_cast<int>(addr - start) % table_entry_size_);
631 return static_cast<int>(addr - start) / table_entry_size_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100632}
633
634
Steve Block9fac8402011-05-12 15:51:54 +0100635int Deoptimizer::GetOutputInfo(DeoptimizationOutputData* data,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000636 BailoutId id,
Steve Block9fac8402011-05-12 15:51:54 +0100637 SharedFunctionInfo* shared) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100638 // TODO(kasperl): For now, we do a simple linear search for the PC
639 // offset associated with the given node id. This should probably be
640 // changed to a binary search.
641 int length = data->DeoptPoints();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100642 for (int i = 0; i < length; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000643 if (data->AstId(i) == id) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100644 return data->PcAndState(i)->value();
645 }
646 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000647 OFStream os(stderr);
648 os << "[couldn't find pc offset for node=" << id.ToInt() << "]\n"
649 << "[method: " << shared->DebugName()->ToCString().get() << "]\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400650 << "[source:\n" << SourceCodeOf(shared) << "\n]" << std::endl;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100651
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000652 shared->GetHeap()->isolate()->PushStackTraceAndDie(0xfefefefe, data, shared,
653 0xfefefeff);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000654 FATAL("unable to find pc offset during deoptimization");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100655 return -1;
656}
657
658
Steve Block44f0eee2011-05-26 01:26:41 +0100659int Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100660 int length = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000661 // Count all entries in the deoptimizing code list of every context.
662 Object* context = isolate->heap()->native_contexts_list();
663 while (!context->IsUndefined()) {
664 Context* native_context = Context::cast(context);
665 Object* element = native_context->DeoptimizedCodeListHead();
666 while (!element->IsUndefined()) {
667 Code* code = Code::cast(element);
668 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
669 length++;
670 element = code->next_code_link();
671 }
Ben Murdochc5610432016-08-08 18:44:38 +0100672 context = Context::cast(context)->next_context_link();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100673 }
674 return length;
675}
676
Ben Murdoch097c5b22016-05-18 11:27:45 +0100677namespace {
678
679int LookupCatchHandler(TranslatedFrame* translated_frame, int* data_out) {
680 switch (translated_frame->kind()) {
681 case TranslatedFrame::kFunction: {
682 BailoutId node_id = translated_frame->node_id();
683 JSFunction* function =
684 JSFunction::cast(translated_frame->begin()->GetRawValue());
685 Code* non_optimized_code = function->shared()->code();
686 FixedArray* raw_data = non_optimized_code->deoptimization_data();
687 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
688 unsigned pc_and_state =
689 Deoptimizer::GetOutputInfo(data, node_id, function->shared());
690 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
691 HandlerTable* table =
692 HandlerTable::cast(non_optimized_code->handler_table());
693 HandlerTable::CatchPrediction prediction;
694 return table->LookupRange(pc_offset, data_out, &prediction);
695 }
696 case TranslatedFrame::kInterpretedFunction: {
697 int bytecode_offset = translated_frame->node_id().ToInt();
698 JSFunction* function =
699 JSFunction::cast(translated_frame->begin()->GetRawValue());
700 BytecodeArray* bytecode = function->shared()->bytecode_array();
701 HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
702 HandlerTable::CatchPrediction prediction;
703 return table->LookupRange(bytecode_offset, data_out, &prediction);
704 }
705 default:
706 break;
707 }
708 return -1;
709}
710
711} // namespace
Ben Murdochb0fe1622011-05-05 13:52:32 +0100712
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100713// We rely on this function not causing a GC. It is called from generated code
714// without having a real stack frame in place.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100715void Deoptimizer::DoComputeOutputFrames() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000716 base::ElapsedTimer timer;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100717
718 // Determine basic deoptimization information. The optimized frame is
719 // described by the input data.
720 DeoptimizationInputData* input_data =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000721 DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
722
Ben Murdochda12d292016-06-02 14:46:10 +0100723 {
724 // Read caller's PC, caller's FP and caller's constant pool values
725 // from input frame. Compute caller's frame top address.
726
727 Register fp_reg = JavaScriptFrame::fp_register();
728 stack_fp_ = input_->GetRegister(fp_reg.code());
729
730 caller_frame_top_ = stack_fp_ + ComputeInputFrameAboveFpFixedSize();
731
732 Address fp_address = input_->GetFramePointerAddress();
733 caller_fp_ = Memory::intptr_at(fp_address);
734 caller_pc_ =
735 Memory::intptr_at(fp_address + CommonFrameConstants::kCallerPCOffset);
736 input_frame_context_ = Memory::intptr_at(
737 fp_address + CommonFrameConstants::kContextOrFrameTypeOffset);
738
739 if (FLAG_enable_embedded_constant_pool) {
740 caller_constant_pool_ = Memory::intptr_at(
741 fp_address + CommonFrameConstants::kConstantPoolOffset);
742 }
743 }
744
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000745 if (trace_scope_ != NULL) {
746 timer.Start();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400747 PrintF(trace_scope_->file(), "[deoptimizing (DEOPT %s): begin ",
748 MessageFor(bailout_type_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000749 PrintFunctionName();
750 PrintF(trace_scope_->file(),
Ben Murdochda12d292016-06-02 14:46:10 +0100751 " (opt #%d) @%d, FP to SP delta: %d, caller sp: 0x%08" V8PRIxPTR
752 "]\n",
753 input_data->OptimizationId()->value(), bailout_id_, fp_to_sp_delta_,
754 caller_frame_top_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000755 if (bailout_type_ == EAGER || bailout_type_ == SOFT ||
756 (compiled_code_->is_hydrogen_stub())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000757 compiled_code_->PrintDeoptLocation(trace_scope_->file(), from_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000758 }
759 }
760
761 BailoutId node_id = input_data->AstId(bailout_id_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100762 ByteArray* translations = input_data->TranslationByteArray();
763 unsigned translation_index =
764 input_data->TranslationIndex(bailout_id_)->value();
765
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000766 TranslationIterator state_iterator(translations, translation_index);
767 translated_state_.Init(
768 input_->GetFramePointerAddress(), &state_iterator,
769 input_data->LiteralArray(), input_->GetRegisterValues(),
770 trace_scope_ == nullptr ? nullptr : trace_scope_->file());
771
Ben Murdochb0fe1622011-05-05 13:52:32 +0100772 // Do the input frame to output frame(s) translation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000773 size_t count = translated_state_.frames().size();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100774 // If we are supposed to go to the catch handler, find the catching frame
775 // for the catch and make sure we only deoptimize upto that frame.
776 if (deoptimizing_throw_) {
777 size_t catch_handler_frame_index = count;
778 for (size_t i = count; i-- > 0;) {
779 catch_handler_pc_offset_ = LookupCatchHandler(
780 &(translated_state_.frames()[i]), &catch_handler_data_);
781 if (catch_handler_pc_offset_ >= 0) {
782 catch_handler_frame_index = i;
783 break;
784 }
785 }
786 CHECK_LT(catch_handler_frame_index, count);
787 count = catch_handler_frame_index + 1;
788 }
789
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000790 DCHECK(output_ == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100791 output_ = new FrameDescription*[count];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000792 for (size_t i = 0; i < count; ++i) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100793 output_[i] = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100794 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000795 output_count_ = static_cast<int>(count);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100796
797 // Translate each output frame.
Ben Murdochda12d292016-06-02 14:46:10 +0100798 int frame_index = 0; // output_frame_index
799 for (size_t i = 0; i < count; ++i, ++frame_index) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100800 // Read the ast node id, function, and frame height for this output frame.
Ben Murdochda12d292016-06-02 14:46:10 +0100801 TranslatedFrame* translated_frame = &(translated_state_.frames()[i]);
802 switch (translated_frame->kind()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000803 case TranslatedFrame::kFunction:
Ben Murdochda12d292016-06-02 14:46:10 +0100804 DoComputeJSFrame(translated_frame, frame_index,
805 deoptimizing_throw_ && i == count - 1);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100806 jsframe_count_++;
807 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000808 case TranslatedFrame::kInterpretedFunction:
Ben Murdochda12d292016-06-02 14:46:10 +0100809 DoComputeInterpretedFrame(translated_frame, frame_index,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100810 deoptimizing_throw_ && i == count - 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000811 jsframe_count_++;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100812 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000813 case TranslatedFrame::kArgumentsAdaptor:
Ben Murdochda12d292016-06-02 14:46:10 +0100814 DoComputeArgumentsAdaptorFrame(translated_frame, frame_index);
815 break;
816 case TranslatedFrame::kTailCallerFunction:
817 DoComputeTailCallerFrame(translated_frame, frame_index);
818 // Tail caller frame translations do not produce output frames.
819 frame_index--;
820 output_count_--;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100821 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000822 case TranslatedFrame::kConstructStub:
Ben Murdochda12d292016-06-02 14:46:10 +0100823 DoComputeConstructStubFrame(translated_frame, frame_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000824 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000825 case TranslatedFrame::kGetter:
Ben Murdochda12d292016-06-02 14:46:10 +0100826 DoComputeAccessorStubFrame(translated_frame, frame_index, false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000827 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000828 case TranslatedFrame::kSetter:
Ben Murdochda12d292016-06-02 14:46:10 +0100829 DoComputeAccessorStubFrame(translated_frame, frame_index, true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000830 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000831 case TranslatedFrame::kCompiledStub:
Ben Murdochda12d292016-06-02 14:46:10 +0100832 DoComputeCompiledStubFrame(translated_frame, frame_index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000833 break;
834 case TranslatedFrame::kInvalid:
835 FATAL("invalid frame");
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100836 break;
837 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100838 }
839
840 // Print some helpful diagnostic information.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000841 if (trace_scope_ != NULL) {
842 double ms = timer.Elapsed().InMillisecondsF();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100843 int index = output_count_ - 1; // Index of the topmost frame.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400844 PrintF(trace_scope_->file(), "[deoptimizing (%s): end ",
845 MessageFor(bailout_type_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000846 PrintFunctionName();
847 PrintF(trace_scope_->file(),
Ben Murdochda12d292016-06-02 14:46:10 +0100848 " @%d => node=%d, pc=0x%08" V8PRIxPTR ", caller sp=0x%08" V8PRIxPTR
849 ", state=%s, took %0.3f ms]\n",
850 bailout_id_, node_id.ToInt(), output_[index]->GetPc(),
Ben Murdochc5610432016-08-08 18:44:38 +0100851 caller_frame_top_, BailoutStateToString(static_cast<BailoutState>(
852 output_[index]->GetState()->value())),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100853 ms);
854 }
855}
856
Ben Murdochda12d292016-06-02 14:46:10 +0100857void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame,
858 int frame_index, bool goto_catch_handler) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100859 SharedFunctionInfo* shared = translated_frame->raw_shared_info();
860
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000861 TranslatedFrame::iterator value_iterator = translated_frame->begin();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100862 bool is_bottommost = (0 == frame_index);
863 bool is_topmost = (output_count_ - 1 == frame_index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000864 int input_index = 0;
865
866 BailoutId node_id = translated_frame->node_id();
867 unsigned height =
868 translated_frame->height() - 1; // Do not count the context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000869 unsigned height_in_bytes = height * kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100870 if (goto_catch_handler) {
871 // Take the stack height from the handler table.
872 height = catch_handler_data_;
873 // We also make space for the exception itself.
874 height_in_bytes = (height + 1) * kPointerSize;
875 CHECK(is_topmost);
876 }
877
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000878 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
879 value_iterator++;
880 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000881 if (trace_scope_ != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000882 PrintF(trace_scope_->file(), " translating frame ");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100883 base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
884 PrintF(trace_scope_->file(), "%s", name.get());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100885 PrintF(trace_scope_->file(), " => node=%d, height=%d%s\n", node_id.ToInt(),
886 height_in_bytes, goto_catch_handler ? " (throw)" : "");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000887 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100888
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000889 // The 'fixed' part of the frame consists of the incoming parameters and
890 // the part described by JavaScriptFrameConstants.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100891 unsigned fixed_frame_size = ComputeJavascriptFixedSize(shared);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000892 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
893
894 // Allocate and store the output frame description.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100895 int parameter_count = shared->internal_formal_parameter_count() + 1;
896 FrameDescription* output_frame = new (output_frame_size)
897 FrameDescription(output_frame_size, parameter_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000898 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
899
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000900 CHECK(frame_index >= 0 && frame_index < output_count_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000901 CHECK_NULL(output_[frame_index]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000902 output_[frame_index] = output_frame;
903
Ben Murdochda12d292016-06-02 14:46:10 +0100904 // The top address of the frame is computed from the previous frame's top and
905 // this frame's size.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000906 intptr_t top_address;
907 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +0100908 top_address = caller_frame_top_ - output_frame_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000909 } else {
910 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
911 }
912 output_frame->SetTop(top_address);
913
914 // Compute the incoming parameter translation.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000915 unsigned output_offset = output_frame_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000916 for (int i = 0; i < parameter_count; ++i) {
917 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000918 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
919 output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000920 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000921
922 // There are no translation commands for the caller's pc and fp, the
923 // context, and the function. Synthesize their values and set them up
924 // explicitly.
925 //
926 // The caller's pc for the bottommost output frame is the same as in the
927 // input frame. For all subsequent output frames, it can be read from the
928 // previous one. This frame's pc can be computed from the non-optimized
929 // function code and AST id of the bailout.
930 output_offset -= kPCOnStackSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000931 intptr_t value;
932 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +0100933 value = caller_pc_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000934 } else {
935 value = output_[frame_index - 1]->GetPc();
936 }
937 output_frame->SetCallerPc(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000938 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000939
940 // The caller's frame pointer for the bottommost output frame is the same
941 // as in the input frame. For all subsequent output frames, it can be
942 // read from the previous one. Also compute and set this frame's frame
943 // pointer.
944 output_offset -= kFPOnStackSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000945 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +0100946 value = caller_fp_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000947 } else {
948 value = output_[frame_index - 1]->GetFp();
949 }
950 output_frame->SetCallerFp(output_offset, value);
951 intptr_t fp_value = top_address + output_offset;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000952 output_frame->SetFp(fp_value);
Ben Murdochda12d292016-06-02 14:46:10 +0100953 if (is_topmost) {
954 Register fp_reg = JavaScriptFrame::fp_register();
955 output_frame->SetRegister(fp_reg.code(), fp_value);
956 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000957 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000958
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000959 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000960 // For the bottommost output frame the constant pool pointer can be gotten
961 // from the input frame. For subsequent output frames, it can be read from
962 // the previous frame.
963 output_offset -= kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000964 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +0100965 value = caller_constant_pool_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000966 } else {
967 value = output_[frame_index - 1]->GetConstantPool();
968 }
969 output_frame->SetCallerConstantPool(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000970 DebugPrintOutputSlot(value, frame_index, output_offset,
971 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000972 }
973
974 // For the bottommost output frame the context can be gotten from the input
975 // frame. For all subsequent output frames it can be gotten from the function
976 // so long as we don't inline functions that need local contexts.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000977 output_offset -= kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100978
979 TranslatedFrame::iterator context_pos = value_iterator;
980 int context_input_index = input_index;
981 // When deoptimizing into a catch block, we need to take the context
982 // from just above the top of the operand stack (we push the context
983 // at the entry of the try block).
984 if (goto_catch_handler) {
985 for (unsigned i = 0; i < height + 1; ++i) {
986 context_pos++;
987 context_input_index++;
988 }
989 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000990 // Read the context from the translations.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100991 Object* context = context_pos->GetRawValue();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000992 if (context == isolate_->heap()->undefined_value()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000993 // If the context was optimized away, just use the context from
994 // the activation. This should only apply to Crankshaft code.
995 CHECK(!compiled_code_->is_turbofanned());
Ben Murdochda12d292016-06-02 14:46:10 +0100996 context = is_bottommost ? reinterpret_cast<Object*>(input_frame_context_)
997 : function->context();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000999 value = reinterpret_cast<intptr_t>(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001000 output_frame->SetContext(value);
Ben Murdochda12d292016-06-02 14:46:10 +01001001 if (is_topmost) {
1002 Register context_reg = JavaScriptFrame::context_register();
1003 output_frame->SetRegister(context_reg.code(), value);
1004 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001005 WriteValueToOutput(context, context_input_index, frame_index, output_offset,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001006 "context ");
1007 if (context == isolate_->heap()->arguments_marker()) {
1008 Address output_address =
1009 reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
1010 output_offset;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001011 values_to_materialize_.push_back({output_address, context_pos});
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001012 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001013 value_iterator++;
1014 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001015
1016 // The function was mentioned explicitly in the BEGIN_FRAME.
1017 output_offset -= kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001018 value = reinterpret_cast<intptr_t>(function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001019 WriteValueToOutput(function, 0, frame_index, output_offset, "function ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001020
1021 // Translate the rest of the frame.
1022 for (unsigned i = 0; i < height; ++i) {
1023 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001024 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1025 output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001026 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001027 if (goto_catch_handler) {
1028 // Write out the exception for the catch handler.
1029 output_offset -= kPointerSize;
1030 Object* exception_obj = reinterpret_cast<Object*>(
1031 input_->GetRegister(FullCodeGenerator::result_register().code()));
1032 WriteValueToOutput(exception_obj, input_index, frame_index, output_offset,
1033 "exception ");
1034 input_index++;
1035 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001036 CHECK_EQ(0u, output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001037
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001038 // Update constant pool.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001039 Code* non_optimized_code = shared->code();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001040 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001041 intptr_t constant_pool_value =
1042 reinterpret_cast<intptr_t>(non_optimized_code->constant_pool());
1043 output_frame->SetConstantPool(constant_pool_value);
1044 if (is_topmost) {
1045 Register constant_pool_reg =
1046 JavaScriptFrame::constant_pool_pointer_register();
1047 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
1048 }
1049 }
1050
Ben Murdoch097c5b22016-05-18 11:27:45 +01001051 // Compute this frame's PC, state, and continuation.
1052 FixedArray* raw_data = non_optimized_code->deoptimization_data();
1053 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
1054 Address start = non_optimized_code->instruction_start();
1055 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared());
1056 unsigned pc_offset = goto_catch_handler
1057 ? catch_handler_pc_offset_
1058 : FullCodeGenerator::PcField::decode(pc_and_state);
1059 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset);
1060 output_frame->SetPc(pc_value);
1061
1062 // If we are going to the catch handler, then the exception lives in
1063 // the accumulator.
Ben Murdochc5610432016-08-08 18:44:38 +01001064 BailoutState state =
1065 goto_catch_handler
1066 ? BailoutState::TOS_REGISTER
1067 : FullCodeGenerator::BailoutStateField::decode(pc_and_state);
1068 output_frame->SetState(Smi::FromInt(static_cast<int>(state)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001069
1070 // Set the continuation for the topmost frame.
Ben Murdochda12d292016-06-02 14:46:10 +01001071 if (is_topmost) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001072 Builtins* builtins = isolate_->builtins();
1073 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
1074 if (bailout_type_ == LAZY) {
1075 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
1076 } else if (bailout_type_ == SOFT) {
1077 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized);
1078 } else {
1079 CHECK_EQ(bailout_type_, EAGER);
1080 }
1081 output_frame->SetContinuation(
1082 reinterpret_cast<intptr_t>(continuation->entry()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001083 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001084}
1085
Ben Murdochda12d292016-06-02 14:46:10 +01001086void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
1087 int frame_index,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001088 bool goto_catch_handler) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001089 SharedFunctionInfo* shared = translated_frame->raw_shared_info();
1090
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001091 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1092 int input_index = 0;
1093
Ben Murdoch097c5b22016-05-18 11:27:45 +01001094 int bytecode_offset = translated_frame->node_id().ToInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001095 unsigned height = translated_frame->height();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001096 unsigned height_in_bytes = height * kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001097 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
1098 value_iterator++;
1099 input_index++;
1100 if (trace_scope_ != NULL) {
1101 PrintF(trace_scope_->file(), " translating interpreted frame ");
Ben Murdoch097c5b22016-05-18 11:27:45 +01001102 base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
1103 PrintF(trace_scope_->file(), "%s", name.get());
1104 PrintF(trace_scope_->file(), " => bytecode_offset=%d, height=%d%s\n",
1105 bytecode_offset, height_in_bytes,
1106 goto_catch_handler ? " (throw)" : "");
1107 }
1108 if (goto_catch_handler) {
1109 bytecode_offset = catch_handler_pc_offset_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001110 }
1111
1112 // The 'fixed' part of the frame consists of the incoming parameters and
1113 // the part described by InterpreterFrameConstants.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001114 unsigned fixed_frame_size = ComputeInterpretedFixedSize(shared);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001115 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1116
1117 // Allocate and store the output frame description.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001118 int parameter_count = shared->internal_formal_parameter_count() + 1;
1119 FrameDescription* output_frame = new (output_frame_size)
1120 FrameDescription(output_frame_size, parameter_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001121 output_frame->SetFrameType(StackFrame::INTERPRETED);
1122
1123 bool is_bottommost = (0 == frame_index);
1124 bool is_topmost = (output_count_ - 1 == frame_index);
1125 CHECK(frame_index >= 0 && frame_index < output_count_);
1126 CHECK_NULL(output_[frame_index]);
1127 output_[frame_index] = output_frame;
1128
Ben Murdochda12d292016-06-02 14:46:10 +01001129 // The top address of the frame is computed from the previous frame's top and
1130 // this frame's size.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001131 intptr_t top_address;
1132 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +01001133 top_address = caller_frame_top_ - output_frame_size;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001134 } else {
1135 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1136 }
1137 output_frame->SetTop(top_address);
1138
1139 // Compute the incoming parameter translation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001140 unsigned output_offset = output_frame_size;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001141 for (int i = 0; i < parameter_count; ++i) {
1142 output_offset -= kPointerSize;
1143 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1144 output_offset);
1145 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001146
1147 // There are no translation commands for the caller's pc and fp, the
1148 // context, the function, new.target and the bytecode offset. Synthesize
1149 // their values and set them up
1150 // explicitly.
1151 //
1152 // The caller's pc for the bottommost output frame is the same as in the
1153 // input frame. For all subsequent output frames, it can be read from the
1154 // previous one. This frame's pc can be computed from the non-optimized
1155 // function code and AST id of the bailout.
1156 output_offset -= kPCOnStackSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001157 intptr_t value;
1158 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +01001159 value = caller_pc_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001160 } else {
1161 value = output_[frame_index - 1]->GetPc();
1162 }
1163 output_frame->SetCallerPc(output_offset, value);
1164 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's pc\n");
1165
1166 // The caller's frame pointer for the bottommost output frame is the same
1167 // as in the input frame. For all subsequent output frames, it can be
1168 // read from the previous one. Also compute and set this frame's frame
1169 // pointer.
1170 output_offset -= kFPOnStackSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001171 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +01001172 value = caller_fp_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001173 } else {
1174 value = output_[frame_index - 1]->GetFp();
1175 }
1176 output_frame->SetCallerFp(output_offset, value);
1177 intptr_t fp_value = top_address + output_offset;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001178 output_frame->SetFp(fp_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001179 if (is_topmost) {
1180 Register fp_reg = InterpretedFrame::fp_register();
1181 output_frame->SetRegister(fp_reg.code(), fp_value);
1182 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001183 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001184
1185 if (FLAG_enable_embedded_constant_pool) {
1186 // For the bottommost output frame the constant pool pointer can be gotten
1187 // from the input frame. For subsequent output frames, it can be read from
1188 // the previous frame.
1189 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001190 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +01001191 value = caller_constant_pool_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001192 } else {
1193 value = output_[frame_index - 1]->GetConstantPool();
1194 }
1195 output_frame->SetCallerConstantPool(output_offset, value);
1196 DebugPrintOutputSlot(value, frame_index, output_offset,
1197 "caller's constant_pool\n");
1198 }
1199
1200 // For the bottommost output frame the context can be gotten from the input
1201 // frame. For all subsequent output frames it can be gotten from the function
1202 // so long as we don't inline functions that need local contexts.
1203 Register context_reg = InterpretedFrame::context_register();
1204 output_offset -= kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001205
1206 // When deoptimizing into a catch block, we need to take the context
1207 // from a register that was specified in the handler table.
1208 TranslatedFrame::iterator context_pos = value_iterator;
1209 int context_input_index = input_index;
1210 if (goto_catch_handler) {
1211 // Skip to the translated value of the register specified
1212 // in the handler table.
1213 for (int i = 0; i < catch_handler_data_ + 1; ++i) {
1214 context_pos++;
1215 context_input_index++;
1216 }
1217 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001218 // Read the context from the translations.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001219 Object* context = context_pos->GetRawValue();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001220 // The context should not be a placeholder for a materialized object.
1221 CHECK(context != isolate_->heap()->arguments_marker());
1222 value = reinterpret_cast<intptr_t>(context);
1223 output_frame->SetContext(value);
1224 if (is_topmost) output_frame->SetRegister(context_reg.code(), value);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001225 WriteValueToOutput(context, context_input_index, frame_index, output_offset,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226 "context ");
1227 value_iterator++;
1228 input_index++;
1229
1230 // The function was mentioned explicitly in the BEGIN_FRAME.
1231 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001232 value = reinterpret_cast<intptr_t>(function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001233 WriteValueToOutput(function, 0, frame_index, output_offset, "function ");
1234
Ben Murdoch097c5b22016-05-18 11:27:45 +01001235 // The new.target slot is only used during function activiation which is
1236 // before the first deopt point, so should never be needed. Just set it to
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001237 // undefined.
1238 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001239 Object* new_target = isolate_->heap()->undefined_value();
1240 WriteValueToOutput(new_target, 0, frame_index, output_offset, "new_target ");
1241
Ben Murdoch097c5b22016-05-18 11:27:45 +01001242 // Set the bytecode array pointer.
1243 output_offset -= kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001244 Object* bytecode_array = shared->bytecode_array();
1245 WriteValueToOutput(bytecode_array, 0, frame_index, output_offset,
1246 "bytecode array ");
1247
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001248 // The bytecode offset was mentioned explicitly in the BEGIN_FRAME.
1249 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001250 int raw_bytecode_offset =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001251 BytecodeArray::kHeaderSize - kHeapObjectTag + bytecode_offset;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001252 Smi* smi_bytecode_offset = Smi::FromInt(raw_bytecode_offset);
1253 WriteValueToOutput(smi_bytecode_offset, 0, frame_index, output_offset,
1254 "bytecode offset ");
1255
1256 // Translate the rest of the interpreter registers in the frame.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001257 for (unsigned i = 0; i < height - 1; ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001258 output_offset -= kPointerSize;
1259 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1260 output_offset);
1261 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001262
1263 // Put the accumulator on the stack. It will be popped by the
1264 // InterpreterNotifyDeopt builtin (possibly after materialization).
1265 output_offset -= kPointerSize;
1266 if (goto_catch_handler) {
1267 // If we are lazy deopting to a catch handler, we set the accumulator to
1268 // the exception (which lives in the result register).
1269 intptr_t accumulator_value =
1270 input_->GetRegister(FullCodeGenerator::result_register().code());
1271 WriteValueToOutput(reinterpret_cast<Object*>(accumulator_value), 0,
1272 frame_index, output_offset, "accumulator ");
1273 value_iterator++;
1274 } else {
1275 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1276 output_offset);
1277 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001278 CHECK_EQ(0u, output_offset);
1279
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001280 Builtins* builtins = isolate_->builtins();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001281 Code* dispatch_builtin =
1282 builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
1283 output_frame->SetPc(reinterpret_cast<intptr_t>(dispatch_builtin->entry()));
Ben Murdochc5610432016-08-08 18:44:38 +01001284 // Restore accumulator (TOS) register.
1285 output_frame->SetState(
1286 Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001287
1288 // Update constant pool.
1289 if (FLAG_enable_embedded_constant_pool) {
1290 intptr_t constant_pool_value =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001291 reinterpret_cast<intptr_t>(dispatch_builtin->constant_pool());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001292 output_frame->SetConstantPool(constant_pool_value);
1293 if (is_topmost) {
1294 Register constant_pool_reg =
1295 InterpretedFrame::constant_pool_pointer_register();
1296 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
1297 }
1298 }
1299
1300 // Set the continuation for the topmost frame.
Ben Murdochda12d292016-06-02 14:46:10 +01001301 if (is_topmost) {
Ben Murdochc5610432016-08-08 18:44:38 +01001302 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001303 if (bailout_type_ == LAZY) {
Ben Murdochc5610432016-08-08 18:44:38 +01001304 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001305 } else if (bailout_type_ == SOFT) {
Ben Murdochc5610432016-08-08 18:44:38 +01001306 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001307 } else {
1308 CHECK_EQ(bailout_type_, EAGER);
1309 }
1310 output_frame->SetContinuation(
1311 reinterpret_cast<intptr_t>(continuation->entry()));
1312 }
1313}
1314
Ben Murdochda12d292016-06-02 14:46:10 +01001315void Deoptimizer::DoComputeArgumentsAdaptorFrame(
1316 TranslatedFrame* translated_frame, int frame_index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001317 TranslatedFrame::iterator value_iterator = translated_frame->begin();
Ben Murdochda12d292016-06-02 14:46:10 +01001318 bool is_bottommost = (0 == frame_index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001319 int input_index = 0;
1320
1321 unsigned height = translated_frame->height();
1322 unsigned height_in_bytes = height * kPointerSize;
1323 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
1324 value_iterator++;
1325 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001326 if (trace_scope_ != NULL) {
1327 PrintF(trace_scope_->file(),
1328 " translating arguments adaptor => height=%d\n", height_in_bytes);
1329 }
1330
Ben Murdochda12d292016-06-02 14:46:10 +01001331 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFixedFrameSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001332 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1333
1334 // Allocate and store the output frame description.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001335 int parameter_count = height;
1336 FrameDescription* output_frame = new (output_frame_size)
1337 FrameDescription(output_frame_size, parameter_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001338 output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);
1339
Ben Murdochda12d292016-06-02 14:46:10 +01001340 // Arguments adaptor can not be topmost.
1341 CHECK(frame_index < output_count_ - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001342 CHECK(output_[frame_index] == NULL);
1343 output_[frame_index] = output_frame;
1344
Ben Murdochda12d292016-06-02 14:46:10 +01001345 // The top address of the frame is computed from the previous frame's top and
1346 // this frame's size.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001347 intptr_t top_address;
Ben Murdochda12d292016-06-02 14:46:10 +01001348 if (is_bottommost) {
1349 top_address = caller_frame_top_ - output_frame_size;
1350 } else {
1351 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1352 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001353 output_frame->SetTop(top_address);
1354
1355 // Compute the incoming parameter translation.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001356 unsigned output_offset = output_frame_size;
1357 for (int i = 0; i < parameter_count; ++i) {
1358 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001359 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1360 output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001361 }
1362
1363 // Read caller's PC from the previous frame.
1364 output_offset -= kPCOnStackSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001365 intptr_t value;
1366 if (is_bottommost) {
1367 value = caller_pc_;
1368 } else {
1369 value = output_[frame_index - 1]->GetPc();
1370 }
1371 output_frame->SetCallerPc(output_offset, value);
1372 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001373
1374 // Read caller's FP from the previous frame, and set this frame's FP.
1375 output_offset -= kFPOnStackSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001376 if (is_bottommost) {
1377 value = caller_fp_;
1378 } else {
1379 value = output_[frame_index - 1]->GetFp();
1380 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001381 output_frame->SetCallerFp(output_offset, value);
1382 intptr_t fp_value = top_address + output_offset;
1383 output_frame->SetFp(fp_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001384 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001385
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001386 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001387 // Read the caller's constant pool from the previous frame.
1388 output_offset -= kPointerSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001389 if (is_bottommost) {
1390 value = caller_constant_pool_;
1391 } else {
1392 value = output_[frame_index - 1]->GetConstantPool();
1393 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001394 output_frame->SetCallerConstantPool(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001395 DebugPrintOutputSlot(value, frame_index, output_offset,
1396 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001397 }
1398
1399 // A marker value is used in place of the context.
1400 output_offset -= kPointerSize;
1401 intptr_t context = reinterpret_cast<intptr_t>(
1402 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1403 output_frame->SetFrameSlot(output_offset, context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001404 DebugPrintOutputSlot(context, frame_index, output_offset,
1405 "context (adaptor sentinel)\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001406
1407 // The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
1408 output_offset -= kPointerSize;
1409 value = reinterpret_cast<intptr_t>(function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001410 WriteValueToOutput(function, 0, frame_index, output_offset, "function ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001411
1412 // Number of incoming arguments.
1413 output_offset -= kPointerSize;
1414 value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
1415 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001416 DebugPrintOutputSlot(value, frame_index, output_offset, "argc ");
1417 if (trace_scope_ != nullptr) {
1418 PrintF(trace_scope_->file(), "(%d)\n", height - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001419 }
1420
1421 DCHECK(0 == output_offset);
1422
1423 Builtins* builtins = isolate_->builtins();
1424 Code* adaptor_trampoline =
1425 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
1426 intptr_t pc_value = reinterpret_cast<intptr_t>(
1427 adaptor_trampoline->instruction_start() +
1428 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
1429 output_frame->SetPc(pc_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001430 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001431 intptr_t constant_pool_value =
1432 reinterpret_cast<intptr_t>(adaptor_trampoline->constant_pool());
1433 output_frame->SetConstantPool(constant_pool_value);
1434 }
1435}
1436
Ben Murdochda12d292016-06-02 14:46:10 +01001437void Deoptimizer::DoComputeTailCallerFrame(TranslatedFrame* translated_frame,
1438 int frame_index) {
1439 SharedFunctionInfo* shared = translated_frame->raw_shared_info();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001440
Ben Murdochda12d292016-06-02 14:46:10 +01001441 bool is_bottommost = (0 == frame_index);
1442 // Tail caller frame can't be topmost.
1443 CHECK_NE(output_count_ - 1, frame_index);
1444
1445 if (trace_scope_ != NULL) {
1446 PrintF(trace_scope_->file(), " translating tail caller frame ");
1447 base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
1448 PrintF(trace_scope_->file(), "%s\n", name.get());
1449 }
1450
1451 if (!is_bottommost) return;
1452
1453 // Drop arguments adaptor frame below current frame if it exsits.
1454 Address fp_address = input_->GetFramePointerAddress();
1455 Address adaptor_fp_address =
1456 Memory::Address_at(fp_address + CommonFrameConstants::kCallerFPOffset);
1457
1458 if (Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR) !=
1459 Memory::Object_at(adaptor_fp_address +
1460 CommonFrameConstants::kContextOrFrameTypeOffset)) {
1461 return;
1462 }
1463
1464 int caller_params_count =
1465 Smi::cast(
1466 Memory::Object_at(adaptor_fp_address +
1467 ArgumentsAdaptorFrameConstants::kLengthOffset))
1468 ->value();
1469
1470 int callee_params_count =
1471 function_->shared()->internal_formal_parameter_count();
1472
1473 // Both caller and callee parameters count do not include receiver.
1474 int offset = (caller_params_count - callee_params_count) * kPointerSize;
1475 intptr_t new_stack_fp =
1476 reinterpret_cast<intptr_t>(adaptor_fp_address) + offset;
1477
1478 intptr_t new_caller_frame_top = new_stack_fp +
1479 (callee_params_count + 1) * kPointerSize +
1480 CommonFrameConstants::kFixedFrameSizeAboveFp;
1481
1482 intptr_t adaptor_caller_pc = Memory::intptr_at(
1483 adaptor_fp_address + CommonFrameConstants::kCallerPCOffset);
1484 intptr_t adaptor_caller_fp = Memory::intptr_at(
1485 adaptor_fp_address + CommonFrameConstants::kCallerFPOffset);
1486
1487 if (trace_scope_ != NULL) {
1488 PrintF(trace_scope_->file(),
1489 " dropping caller arguments adaptor frame: offset=%d, "
1490 "fp: 0x%08" V8PRIxPTR " -> 0x%08" V8PRIxPTR
1491 ", "
1492 "caller sp: 0x%08" V8PRIxPTR " -> 0x%08" V8PRIxPTR "\n",
1493 offset, stack_fp_, new_stack_fp, caller_frame_top_,
1494 new_caller_frame_top);
1495 }
1496 caller_frame_top_ = new_caller_frame_top;
1497 caller_fp_ = adaptor_caller_fp;
1498 caller_pc_ = adaptor_caller_pc;
1499}
1500
1501void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
1502 int frame_index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001503 TranslatedFrame::iterator value_iterator = translated_frame->begin();
Ben Murdochda12d292016-06-02 14:46:10 +01001504 bool is_topmost = (output_count_ - 1 == frame_index);
1505 // The construct frame could become topmost only if we inlined a constructor
1506 // call which does a tail call (otherwise the tail callee's frame would be
1507 // the topmost one). So it could only be the LAZY case.
1508 CHECK(!is_topmost || bailout_type_ == LAZY);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001509 int input_index = 0;
1510
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001511 Builtins* builtins = isolate_->builtins();
1512 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001513 unsigned height = translated_frame->height();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001514 unsigned height_in_bytes = height * kPointerSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001515
1516 // If the construct frame appears to be topmost we should ensure that the
1517 // value of result register is preserved during continuation execution.
1518 // We do this here by "pushing" the result of the constructor function to the
1519 // top of the reconstructed stack and then using the
Ben Murdochc5610432016-08-08 18:44:38 +01001520 // BailoutState::TOS_REGISTER machinery.
Ben Murdochda12d292016-06-02 14:46:10 +01001521 if (is_topmost) {
1522 height_in_bytes += kPointerSize;
1523 }
1524
Ben Murdoch097c5b22016-05-18 11:27:45 +01001525 // Skip function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001526 value_iterator++;
1527 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001528 if (trace_scope_ != NULL) {
1529 PrintF(trace_scope_->file(),
1530 " translating construct stub => height=%d\n", height_in_bytes);
1531 }
1532
Ben Murdochda12d292016-06-02 14:46:10 +01001533 unsigned fixed_frame_size = ConstructFrameConstants::kFixedFrameSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001534 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1535
1536 // Allocate and store the output frame description.
1537 FrameDescription* output_frame =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001538 new (output_frame_size) FrameDescription(output_frame_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001539 output_frame->SetFrameType(StackFrame::CONSTRUCT);
1540
Ben Murdochda12d292016-06-02 14:46:10 +01001541 // Construct stub can not be topmost.
1542 DCHECK(frame_index > 0 && frame_index < output_count_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001543 DCHECK(output_[frame_index] == NULL);
1544 output_[frame_index] = output_frame;
1545
Ben Murdochda12d292016-06-02 14:46:10 +01001546 // The top address of the frame is computed from the previous frame's top and
1547 // this frame's size.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001548 intptr_t top_address;
1549 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1550 output_frame->SetTop(top_address);
1551
1552 // Compute the incoming parameter translation.
1553 int parameter_count = height;
1554 unsigned output_offset = output_frame_size;
1555 for (int i = 0; i < parameter_count; ++i) {
1556 output_offset -= kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001557 // The allocated receiver of a construct stub frame is passed as the
1558 // receiver parameter through the translation. It might be encoding
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001559 // a captured object, override the slot address for a captured object.
1560 WriteTranslatedValueToOutput(
1561 &value_iterator, &input_index, frame_index, output_offset, nullptr,
1562 (i == 0) ? reinterpret_cast<Address>(top_address) : nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001563 }
1564
1565 // Read caller's PC from the previous frame.
1566 output_offset -= kPCOnStackSize;
1567 intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1568 output_frame->SetCallerPc(output_offset, callers_pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001569 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001570
1571 // Read caller's FP from the previous frame, and set this frame's FP.
1572 output_offset -= kFPOnStackSize;
1573 intptr_t value = output_[frame_index - 1]->GetFp();
1574 output_frame->SetCallerFp(output_offset, value);
1575 intptr_t fp_value = top_address + output_offset;
1576 output_frame->SetFp(fp_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001577 if (is_topmost) {
1578 Register fp_reg = JavaScriptFrame::fp_register();
1579 output_frame->SetRegister(fp_reg.code(), fp_value);
1580 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001581 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001582
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001583 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001584 // Read the caller's constant pool from the previous frame.
1585 output_offset -= kPointerSize;
1586 value = output_[frame_index - 1]->GetConstantPool();
1587 output_frame->SetCallerConstantPool(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001588 DebugPrintOutputSlot(value, frame_index, output_offset,
1589 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001590 }
1591
Ben Murdochda12d292016-06-02 14:46:10 +01001592 // A marker value is used to mark the frame.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001593 output_offset -= kPointerSize;
1594 value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT));
1595 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001596 DebugPrintOutputSlot(value, frame_index, output_offset,
Ben Murdochda12d292016-06-02 14:46:10 +01001597 "typed frame marker\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001598
Ben Murdochda12d292016-06-02 14:46:10 +01001599 // The context can be gotten from the previous frame.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001600 output_offset -= kPointerSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001601 value = output_[frame_index - 1]->GetContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001602 output_frame->SetFrameSlot(output_offset, value);
Ben Murdochda12d292016-06-02 14:46:10 +01001603 if (is_topmost) {
1604 Register context_reg = JavaScriptFrame::context_register();
1605 output_frame->SetRegister(context_reg.code(), value);
1606 }
1607 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001608
1609 // The allocation site.
1610 output_offset -= kPointerSize;
1611 value = reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value());
1612 output_frame->SetFrameSlot(output_offset, value);
1613 DebugPrintOutputSlot(value, frame_index, output_offset, "allocation site\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001614
1615 // Number of incoming arguments.
1616 output_offset -= kPointerSize;
1617 value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
1618 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001619 DebugPrintOutputSlot(value, frame_index, output_offset, "argc ");
1620 if (trace_scope_ != nullptr) {
1621 PrintF(trace_scope_->file(), "(%d)\n", height - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001622 }
1623
1624 // The newly allocated object was passed as receiver in the artificial
1625 // constructor stub environment created by HEnvironment::CopyForInlining().
1626 output_offset -= kPointerSize;
1627 value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
1628 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001629 DebugPrintOutputSlot(value, frame_index, output_offset,
1630 "allocated receiver\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001631
Ben Murdochda12d292016-06-02 14:46:10 +01001632 if (is_topmost) {
1633 // Ensure the result is restored back when we return to the stub.
1634 output_offset -= kPointerSize;
1635 Register result_reg = FullCodeGenerator::result_register();
1636 value = input_->GetRegister(result_reg.code());
1637 output_frame->SetFrameSlot(output_offset, value);
1638 DebugPrintOutputSlot(value, frame_index, output_offset,
1639 "constructor result\n");
1640
Ben Murdochc5610432016-08-08 18:44:38 +01001641 output_frame->SetState(
1642 Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER)));
Ben Murdochda12d292016-06-02 14:46:10 +01001643 }
1644
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001645 CHECK_EQ(0u, output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001646
1647 intptr_t pc = reinterpret_cast<intptr_t>(
1648 construct_stub->instruction_start() +
1649 isolate_->heap()->construct_stub_deopt_pc_offset()->value());
1650 output_frame->SetPc(pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001651 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001652 intptr_t constant_pool_value =
1653 reinterpret_cast<intptr_t>(construct_stub->constant_pool());
1654 output_frame->SetConstantPool(constant_pool_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001655 if (is_topmost) {
1656 Register constant_pool_reg =
1657 JavaScriptFrame::constant_pool_pointer_register();
1658 output_frame->SetRegister(constant_pool_reg.code(), fp_value);
1659 }
1660 }
1661
1662 // Set the continuation for the topmost frame.
1663 if (is_topmost) {
1664 Builtins* builtins = isolate_->builtins();
1665 DCHECK_EQ(LAZY, bailout_type_);
1666 Code* continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
1667 output_frame->SetContinuation(
1668 reinterpret_cast<intptr_t>(continuation->entry()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001669 }
1670}
1671
Ben Murdochda12d292016-06-02 14:46:10 +01001672void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
1673 int frame_index,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001674 bool is_setter_stub_frame) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001675 TranslatedFrame::iterator value_iterator = translated_frame->begin();
Ben Murdochda12d292016-06-02 14:46:10 +01001676 bool is_topmost = (output_count_ - 1 == frame_index);
1677 // The accessor frame could become topmost only if we inlined an accessor
1678 // call which does a tail call (otherwise the tail callee's frame would be
1679 // the topmost one). So it could only be the LAZY case.
1680 CHECK(!is_topmost || bailout_type_ == LAZY);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001681 int input_index = 0;
1682
Ben Murdoch097c5b22016-05-18 11:27:45 +01001683 // Skip accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001684 value_iterator++;
1685 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001686 // The receiver (and the implicit return value, if any) are expected in
1687 // registers by the LoadIC/StoreIC, so they don't belong to the output stack
1688 // frame. This means that we have to use a height of 0.
1689 unsigned height = 0;
1690 unsigned height_in_bytes = height * kPointerSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001691
1692 // If the accessor frame appears to be topmost we should ensure that the
1693 // value of result register is preserved during continuation execution.
1694 // We do this here by "pushing" the result of the accessor function to the
1695 // top of the reconstructed stack and then using the
Ben Murdochc5610432016-08-08 18:44:38 +01001696 // BailoutState::TOS_REGISTER machinery.
Ben Murdochda12d292016-06-02 14:46:10 +01001697 // We don't need to restore the result in case of a setter call because we
1698 // have to return the stored value but not the result of the setter function.
1699 bool should_preserve_result = is_topmost && !is_setter_stub_frame;
1700 if (should_preserve_result) {
1701 height_in_bytes += kPointerSize;
1702 }
1703
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001704 const char* kind = is_setter_stub_frame ? "setter" : "getter";
1705 if (trace_scope_ != NULL) {
1706 PrintF(trace_scope_->file(),
1707 " translating %s stub => height=%u\n", kind, height_in_bytes);
1708 }
1709
1710 // We need 1 stack entry for the return address and enough entries for the
Ben Murdochda12d292016-06-02 14:46:10 +01001711 // StackFrame::INTERNAL (FP, frame type, context, code object and constant
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001712 // pool (if enabled)- see MacroAssembler::EnterFrame).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001713 // For a setter stub frame we need one additional entry for the implicit
1714 // return value, see StoreStubCompiler::CompileStoreViaSetter.
1715 unsigned fixed_frame_entries =
1716 (StandardFrameConstants::kFixedFrameSize / kPointerSize) + 1 +
1717 (is_setter_stub_frame ? 1 : 0);
1718 unsigned fixed_frame_size = fixed_frame_entries * kPointerSize;
1719 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1720
1721 // Allocate and store the output frame description.
1722 FrameDescription* output_frame =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001723 new (output_frame_size) FrameDescription(output_frame_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001724 output_frame->SetFrameType(StackFrame::INTERNAL);
1725
Ben Murdochda12d292016-06-02 14:46:10 +01001726 // A frame for an accessor stub can not be bottommost.
1727 CHECK(frame_index > 0 && frame_index < output_count_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001728 CHECK_NULL(output_[frame_index]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001729 output_[frame_index] = output_frame;
1730
1731 // The top address of the frame is computed from the previous frame's top and
1732 // this frame's size.
1733 intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1734 output_frame->SetTop(top_address);
1735
1736 unsigned output_offset = output_frame_size;
1737
1738 // Read caller's PC from the previous frame.
1739 output_offset -= kPCOnStackSize;
1740 intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1741 output_frame->SetCallerPc(output_offset, callers_pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001742 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001743
1744 // Read caller's FP from the previous frame, and set this frame's FP.
1745 output_offset -= kFPOnStackSize;
1746 intptr_t value = output_[frame_index - 1]->GetFp();
1747 output_frame->SetCallerFp(output_offset, value);
1748 intptr_t fp_value = top_address + output_offset;
1749 output_frame->SetFp(fp_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001750 if (is_topmost) {
1751 Register fp_reg = JavaScriptFrame::fp_register();
1752 output_frame->SetRegister(fp_reg.code(), fp_value);
1753 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001754 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001755
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001756 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001757 // Read the caller's constant pool from the previous frame.
1758 output_offset -= kPointerSize;
1759 value = output_[frame_index - 1]->GetConstantPool();
1760 output_frame->SetCallerConstantPool(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001761 DebugPrintOutputSlot(value, frame_index, output_offset,
1762 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001763 }
1764
Ben Murdochda12d292016-06-02 14:46:10 +01001765 // Set the frame type.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001766 output_offset -= kPointerSize;
1767 value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::INTERNAL));
1768 output_frame->SetFrameSlot(output_offset, value);
Ben Murdochda12d292016-06-02 14:46:10 +01001769 DebugPrintOutputSlot(value, frame_index, output_offset, "frame type ");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001770 if (trace_scope_ != nullptr) {
1771 PrintF(trace_scope_->file(), "(%s sentinel)\n", kind);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001772 }
1773
1774 // Get Code object from accessor stub.
1775 output_offset -= kPointerSize;
1776 Builtins::Name name = is_setter_stub_frame ?
1777 Builtins::kStoreIC_Setter_ForDeopt :
1778 Builtins::kLoadIC_Getter_ForDeopt;
1779 Code* accessor_stub = isolate_->builtins()->builtin(name);
1780 value = reinterpret_cast<intptr_t>(accessor_stub);
1781 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001782 DebugPrintOutputSlot(value, frame_index, output_offset, "code object\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001783
Ben Murdochda12d292016-06-02 14:46:10 +01001784 // The context can be gotten from the previous frame.
1785 output_offset -= kPointerSize;
1786 value = output_[frame_index - 1]->GetContext();
1787 output_frame->SetFrameSlot(output_offset, value);
1788 if (is_topmost) {
1789 Register context_reg = JavaScriptFrame::context_register();
1790 output_frame->SetRegister(context_reg.code(), value);
1791 }
1792 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
1793
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001794 // Skip receiver.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001795 value_iterator++;
1796 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001797
1798 if (is_setter_stub_frame) {
1799 // The implicit return value was part of the artificial setter stub
1800 // environment.
1801 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001802 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1803 output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001804 }
1805
Ben Murdochda12d292016-06-02 14:46:10 +01001806 if (should_preserve_result) {
1807 // Ensure the result is restored back when we return to the stub.
1808 output_offset -= kPointerSize;
1809 Register result_reg = FullCodeGenerator::result_register();
1810 value = input_->GetRegister(result_reg.code());
1811 output_frame->SetFrameSlot(output_offset, value);
1812 DebugPrintOutputSlot(value, frame_index, output_offset,
1813 "accessor result\n");
1814
Ben Murdochc5610432016-08-08 18:44:38 +01001815 output_frame->SetState(
1816 Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER)));
Ben Murdochda12d292016-06-02 14:46:10 +01001817 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01001818 output_frame->SetState(
1819 Smi::FromInt(static_cast<int>(BailoutState::NO_REGISTERS)));
Ben Murdochda12d292016-06-02 14:46:10 +01001820 }
1821
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001822 CHECK_EQ(0u, output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001823
1824 Smi* offset = is_setter_stub_frame ?
1825 isolate_->heap()->setter_stub_deopt_pc_offset() :
1826 isolate_->heap()->getter_stub_deopt_pc_offset();
1827 intptr_t pc = reinterpret_cast<intptr_t>(
1828 accessor_stub->instruction_start() + offset->value());
1829 output_frame->SetPc(pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001830 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001831 intptr_t constant_pool_value =
1832 reinterpret_cast<intptr_t>(accessor_stub->constant_pool());
1833 output_frame->SetConstantPool(constant_pool_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001834 if (is_topmost) {
1835 Register constant_pool_reg =
1836 JavaScriptFrame::constant_pool_pointer_register();
1837 output_frame->SetRegister(constant_pool_reg.code(), fp_value);
1838 }
1839 }
1840
1841 // Set the continuation for the topmost frame.
1842 if (is_topmost) {
1843 Builtins* builtins = isolate_->builtins();
1844 DCHECK_EQ(LAZY, bailout_type_);
1845 Code* continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
1846 output_frame->SetContinuation(
1847 reinterpret_cast<intptr_t>(continuation->entry()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001848 }
1849}
1850
Ben Murdochda12d292016-06-02 14:46:10 +01001851void Deoptimizer::DoComputeCompiledStubFrame(TranslatedFrame* translated_frame,
1852 int frame_index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001853 //
1854 // FROM TO
1855 // | .... | | .... |
1856 // +-------------------------+ +-------------------------+
1857 // | JSFunction continuation | | JSFunction continuation |
1858 // +-------------------------+ +-------------------------+
1859 // | | saved frame (FP) | | saved frame (FP) |
1860 // | +=========================+<-fpreg +=========================+<-fpreg
1861 // | |constant pool (if ool_cp)| |constant pool (if ool_cp)|
1862 // | +-------------------------+ +-------------------------|
1863 // | | JSFunction context | | JSFunction context |
1864 // v +-------------------------+ +-------------------------|
1865 // | COMPILED_STUB marker | | STUB_FAILURE marker |
1866 // +-------------------------+ +-------------------------+
1867 // | | | caller args.arguments_ |
1868 // | ... | +-------------------------+
1869 // | | | caller args.length_ |
1870 // |-------------------------|<-spreg +-------------------------+
1871 // | caller args pointer |
1872 // +-------------------------+
1873 // | caller stack param 1 |
1874 // parameters in registers +-------------------------+
1875 // and spilled to stack | .... |
1876 // +-------------------------+
1877 // | caller stack param n |
1878 // +-------------------------+<-spreg
1879 // reg = number of parameters
1880 // reg = failure handler address
1881 // reg = saved frame
1882 // reg = JSFunction context
1883 //
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001884 // Caller stack params contain the register parameters to the stub first,
1885 // and then, if the descriptor specifies a constant number of stack
1886 // parameters, the stack parameters as well.
1887
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001888 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1889 int input_index = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001890
1891 CHECK(compiled_code_->is_hydrogen_stub());
1892 int major_key = CodeStub::GetMajorKey(compiled_code_);
1893 CodeStubDescriptor descriptor(isolate_, compiled_code_->stub_key());
1894
1895 // The output frame must have room for all pushed register parameters
1896 // and the standard stack frame slots. Include space for an argument
1897 // object to the callee and optionally the space to pass the argument
1898 // object to the stub failure handler.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001899 int param_count = descriptor.GetRegisterParameterCount();
1900 int stack_param_count = descriptor.GetStackParameterCount();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001901 // The translated frame contains all of the register parameters
1902 // plus the context.
1903 CHECK_EQ(translated_frame->height(), param_count + 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001904 CHECK_GE(param_count, 0);
1905
Ben Murdochda12d292016-06-02 14:46:10 +01001906 int height_in_bytes = kPointerSize * (param_count + stack_param_count);
1907 int fixed_frame_size = StubFailureTrampolineFrameConstants::kFixedFrameSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001908 int output_frame_size = height_in_bytes + fixed_frame_size;
1909 if (trace_scope_ != NULL) {
1910 PrintF(trace_scope_->file(),
1911 " translating %s => StubFailureTrampolineStub, height=%d\n",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001912 CodeStub::MajorName(static_cast<CodeStub::Major>(major_key)),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001913 height_in_bytes);
1914 }
1915
1916 // The stub failure trampoline is a single frame.
1917 FrameDescription* output_frame =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001918 new (output_frame_size) FrameDescription(output_frame_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001919 output_frame->SetFrameType(StackFrame::STUB_FAILURE_TRAMPOLINE);
1920 CHECK_EQ(frame_index, 0);
1921 output_[frame_index] = output_frame;
1922
Ben Murdochda12d292016-06-02 14:46:10 +01001923 // The top address of the frame is computed from the previous frame's top and
1924 // this frame's size.
1925 intptr_t top_address = caller_frame_top_ - output_frame_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001926 output_frame->SetTop(top_address);
1927
Ben Murdochda12d292016-06-02 14:46:10 +01001928 // Set caller's PC (JSFunction continuation).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001929 unsigned output_frame_offset = output_frame_size - kFPOnStackSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001930 intptr_t value = caller_pc_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001931 output_frame->SetCallerPc(output_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001932 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
1933 "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001934
1935 // Read caller's FP from the input frame, and set this frame's FP.
Ben Murdochda12d292016-06-02 14:46:10 +01001936 value = caller_fp_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001937 output_frame_offset -= kFPOnStackSize;
1938 output_frame->SetCallerFp(output_frame_offset, value);
Ben Murdochda12d292016-06-02 14:46:10 +01001939 intptr_t frame_ptr = top_address + output_frame_offset;
1940 Register fp_reg = StubFailureTrampolineFrame::fp_register();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001941 output_frame->SetRegister(fp_reg.code(), frame_ptr);
1942 output_frame->SetFp(frame_ptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001943 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
1944 "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001945
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001946 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001947 // Read the caller's constant pool from the input frame.
Ben Murdochda12d292016-06-02 14:46:10 +01001948 value = caller_constant_pool_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001949 output_frame_offset -= kPointerSize;
1950 output_frame->SetCallerConstantPool(output_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001951 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
1952 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001953 }
1954
Ben Murdochda12d292016-06-02 14:46:10 +01001955 // The marker for the typed stack frame
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001956 output_frame_offset -= kPointerSize;
1957 value = reinterpret_cast<intptr_t>(
1958 Smi::FromInt(StackFrame::STUB_FAILURE_TRAMPOLINE));
1959 output_frame->SetFrameSlot(output_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001960 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
1961 "function (stub failure sentinel)\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001962
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001963 intptr_t caller_arg_count = stack_param_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001964 bool arg_count_known = !descriptor.stack_parameter_count().is_valid();
1965
1966 // Build the Arguments object for the caller's parameters and a pointer to it.
1967 output_frame_offset -= kPointerSize;
1968 int args_arguments_offset = output_frame_offset;
1969 intptr_t the_hole = reinterpret_cast<intptr_t>(
1970 isolate_->heap()->the_hole_value());
1971 if (arg_count_known) {
1972 value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
1973 (caller_arg_count - 1) * kPointerSize;
1974 } else {
1975 value = the_hole;
1976 }
1977
1978 output_frame->SetFrameSlot(args_arguments_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001979 DebugPrintOutputSlot(
1980 value, frame_index, args_arguments_offset,
1981 arg_count_known ? "args.arguments\n" : "args.arguments (the hole)\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001982
1983 output_frame_offset -= kPointerSize;
1984 int length_frame_offset = output_frame_offset;
1985 value = arg_count_known ? caller_arg_count : the_hole;
1986 output_frame->SetFrameSlot(length_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001987 DebugPrintOutputSlot(
1988 value, frame_index, length_frame_offset,
1989 arg_count_known ? "args.length\n" : "args.length (the hole)\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001990
1991 output_frame_offset -= kPointerSize;
1992 value = frame_ptr + StandardFrameConstants::kCallerSPOffset -
1993 (output_frame_size - output_frame_offset) + kPointerSize;
1994 output_frame->SetFrameSlot(output_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001995 DebugPrintOutputSlot(value, frame_index, output_frame_offset, "args*\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001996
1997 // Copy the register parameters to the failure frame.
1998 int arguments_length_offset = -1;
1999 for (int i = 0; i < param_count; ++i) {
2000 output_frame_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002001 WriteTranslatedValueToOutput(&value_iterator, &input_index, 0,
2002 output_frame_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002003
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002004 if (!arg_count_known &&
2005 descriptor.GetRegisterParameter(i)
2006 .is(descriptor.stack_parameter_count())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002007 arguments_length_offset = output_frame_offset;
2008 }
2009 }
2010
Ben Murdoch097c5b22016-05-18 11:27:45 +01002011 Object* maybe_context = value_iterator->GetRawValue();
2012 CHECK(maybe_context->IsContext());
2013 Register context_reg = StubFailureTrampolineFrame::context_register();
2014 value = reinterpret_cast<intptr_t>(maybe_context);
2015 output_frame->SetRegister(context_reg.code(), value);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002016 ++value_iterator;
2017
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002018 // Copy constant stack parameters to the failure frame. If the number of stack
2019 // parameters is not known in the descriptor, the arguments object is the way
2020 // to access them.
2021 for (int i = 0; i < stack_param_count; i++) {
2022 output_frame_offset -= kPointerSize;
2023 Object** stack_parameter = reinterpret_cast<Object**>(
2024 frame_ptr + StandardFrameConstants::kCallerSPOffset +
2025 (stack_param_count - i - 1) * kPointerSize);
2026 value = reinterpret_cast<intptr_t>(*stack_parameter);
2027 output_frame->SetFrameSlot(output_frame_offset, value);
2028 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
2029 "stack parameter\n");
2030 }
2031
2032 CHECK_EQ(0u, output_frame_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002033
2034 if (!arg_count_known) {
2035 CHECK_GE(arguments_length_offset, 0);
2036 // We know it's a smi because 1) the code stub guarantees the stack
2037 // parameter count is in smi range, and 2) the DoTranslateCommand in the
2038 // parameter loop above translated that to a tagged value.
2039 Smi* smi_caller_arg_count = reinterpret_cast<Smi*>(
2040 output_frame->GetFrameSlot(arguments_length_offset));
2041 caller_arg_count = smi_caller_arg_count->value();
2042 output_frame->SetFrameSlot(length_frame_offset, caller_arg_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002043 DebugPrintOutputSlot(caller_arg_count, frame_index, length_frame_offset,
2044 "args.length\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002045 value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
2046 (caller_arg_count - 1) * kPointerSize;
2047 output_frame->SetFrameSlot(args_arguments_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002048 DebugPrintOutputSlot(value, frame_index, args_arguments_offset,
2049 "args.arguments");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002050 }
2051
2052 // Copy the double registers from the input into the output frame.
2053 CopyDoubleRegisters(output_frame);
2054
2055 // Fill registers containing handler and number of parameters.
2056 SetPlatformCompiledStubRegisters(output_frame, &descriptor);
2057
2058 // Compute this frame's PC, state, and continuation.
2059 Code* trampoline = NULL;
2060 StubFunctionMode function_mode = descriptor.function_mode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002061 StubFailureTrampolineStub(isolate_, function_mode)
2062 .FindCodeInCache(&trampoline);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002063 DCHECK(trampoline != NULL);
2064 output_frame->SetPc(reinterpret_cast<intptr_t>(
2065 trampoline->instruction_start()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002066 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002067 Register constant_pool_reg =
2068 StubFailureTrampolineFrame::constant_pool_pointer_register();
2069 intptr_t constant_pool_value =
2070 reinterpret_cast<intptr_t>(trampoline->constant_pool());
2071 output_frame->SetConstantPool(constant_pool_value);
2072 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
2073 }
Ben Murdochc5610432016-08-08 18:44:38 +01002074 output_frame->SetState(
2075 Smi::FromInt(static_cast<int>(BailoutState::NO_REGISTERS)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002076 Code* notify_failure =
2077 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles);
2078 output_frame->SetContinuation(
2079 reinterpret_cast<intptr_t>(notify_failure->entry()));
2080}
2081
2082
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002083void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002084 // Walk to the last JavaScript output frame to find out if it has
2085 // adapted arguments.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002086 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
2087 if (frame_index != 0) it->Advance();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002088 }
Ben Murdochda12d292016-06-02 14:46:10 +01002089 translated_state_.Prepare(it->frame()->has_adapted_arguments(),
2090 reinterpret_cast<Address>(stack_fp_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002091
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002092 for (auto& materialization : values_to_materialize_) {
2093 Handle<Object> value = materialization.value_->GetValue();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002094
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002095 if (trace_scope_ != nullptr) {
2096 PrintF("Materialization [0x%08" V8PRIxPTR "] <- 0x%08" V8PRIxPTR " ; ",
2097 reinterpret_cast<intptr_t>(materialization.output_slot_address_),
2098 reinterpret_cast<intptr_t>(*value));
2099 value->ShortPrint(trace_scope_->file());
2100 PrintF(trace_scope_->file(), "\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002101 }
2102
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002103 *(reinterpret_cast<intptr_t*>(materialization.output_slot_address_)) =
2104 reinterpret_cast<intptr_t>(*value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002105 }
2106
Ben Murdochda12d292016-06-02 14:46:10 +01002107 isolate_->materialized_object_store()->Remove(
2108 reinterpret_cast<Address>(stack_fp_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002109}
2110
2111
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002112void Deoptimizer::WriteTranslatedValueToOutput(
2113 TranslatedFrame::iterator* iterator, int* input_index, int frame_index,
2114 unsigned output_offset, const char* debug_hint_string,
2115 Address output_address_for_materialization) {
2116 Object* value = (*iterator)->GetRawValue();
2117
2118 WriteValueToOutput(value, *input_index, frame_index, output_offset,
2119 debug_hint_string);
2120
2121 if (value == isolate_->heap()->arguments_marker()) {
2122 Address output_address =
2123 reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
2124 output_offset;
2125 if (output_address_for_materialization == nullptr) {
2126 output_address_for_materialization = output_address;
2127 }
2128 values_to_materialize_.push_back(
2129 {output_address_for_materialization, *iterator});
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002130 }
2131
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002132 (*iterator)++;
2133 (*input_index)++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002134}
2135
2136
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002137void Deoptimizer::WriteValueToOutput(Object* value, int input_index,
2138 int frame_index, unsigned output_offset,
2139 const char* debug_hint_string) {
2140 output_[frame_index]->SetFrameSlot(output_offset,
2141 reinterpret_cast<intptr_t>(value));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002142
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002143 if (trace_scope_ != nullptr) {
2144 DebugPrintOutputSlot(reinterpret_cast<intptr_t>(value), frame_index,
2145 output_offset, debug_hint_string);
2146 value->ShortPrint(trace_scope_->file());
2147 PrintF(trace_scope_->file(), " (input #%d)\n", input_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002148 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002149}
2150
2151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002152void Deoptimizer::DebugPrintOutputSlot(intptr_t value, int frame_index,
2153 unsigned output_offset,
2154 const char* debug_hint_string) {
2155 if (trace_scope_ != nullptr) {
2156 Address output_address =
2157 reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
2158 output_offset;
2159 PrintF(trace_scope_->file(),
2160 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s",
2161 reinterpret_cast<intptr_t>(output_address), output_offset, value,
2162 debug_hint_string == nullptr ? "" : debug_hint_string);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002163 }
2164}
2165
Ben Murdochda12d292016-06-02 14:46:10 +01002166unsigned Deoptimizer::ComputeInputFrameAboveFpFixedSize() const {
2167 unsigned fixed_size = CommonFrameConstants::kFixedFrameSizeAboveFp;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002168 if (!function_->IsSmi()) {
2169 fixed_size += ComputeIncomingArgumentSize(function_->shared());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002170 }
Ben Murdochda12d292016-06-02 14:46:10 +01002171 return fixed_size;
2172}
2173
2174unsigned Deoptimizer::ComputeInputFrameSize() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002175 // The fp-to-sp delta already takes the context, constant pool pointer and the
2176 // function into account so we have to avoid double counting them.
Ben Murdochda12d292016-06-02 14:46:10 +01002177 unsigned fixed_size_above_fp = ComputeInputFrameAboveFpFixedSize();
2178 unsigned result = fixed_size_above_fp + fp_to_sp_delta_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002179 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
2180 unsigned stack_slots = compiled_code_->stack_slots();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002181 unsigned outgoing_size =
2182 ComputeOutgoingArgumentSize(compiled_code_, bailout_id_);
Ben Murdochda12d292016-06-02 14:46:10 +01002183 CHECK_EQ(fixed_size_above_fp + (stack_slots * kPointerSize) -
2184 CommonFrameConstants::kFixedFrameSizeAboveFp + outgoing_size,
2185 result);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002186 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01002187 return result;
2188}
2189
Ben Murdoch097c5b22016-05-18 11:27:45 +01002190// static
2191unsigned Deoptimizer::ComputeJavascriptFixedSize(SharedFunctionInfo* shared) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002192 // The fixed part of the frame consists of the return address, frame
2193 // pointer, function, context, and all the incoming arguments.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002194 return ComputeIncomingArgumentSize(shared) +
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002195 StandardFrameConstants::kFixedFrameSize;
2196}
2197
Ben Murdoch097c5b22016-05-18 11:27:45 +01002198// static
2199unsigned Deoptimizer::ComputeInterpretedFixedSize(SharedFunctionInfo* shared) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002200 // The fixed part of the frame consists of the return address, frame
2201 // pointer, function, context, new.target, bytecode offset and all the
2202 // incoming arguments.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002203 return ComputeIncomingArgumentSize(shared) +
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002204 InterpreterFrameConstants::kFixedFrameSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002205}
2206
Ben Murdoch097c5b22016-05-18 11:27:45 +01002207// static
2208unsigned Deoptimizer::ComputeIncomingArgumentSize(SharedFunctionInfo* shared) {
2209 return (shared->internal_formal_parameter_count() + 1) * kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002210}
2211
2212
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002213// static
2214unsigned Deoptimizer::ComputeOutgoingArgumentSize(Code* code,
2215 unsigned bailout_id) {
2216 DeoptimizationInputData* data =
2217 DeoptimizationInputData::cast(code->deoptimization_data());
2218 unsigned height = data->ArgumentsStackHeight(bailout_id)->value();
Ben Murdochb0fe1622011-05-05 13:52:32 +01002219 return height * kPointerSize;
2220}
2221
2222
2223Object* Deoptimizer::ComputeLiteral(int index) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002224 DeoptimizationInputData* data =
2225 DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002226 FixedArray* literals = data->LiteralArray();
2227 return literals->get(index);
2228}
2229
2230
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002231void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate,
2232 BailoutType type,
2233 int max_entry_id) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002234 // We cannot run this if the serializer is enabled because this will
2235 // cause us to emit relocation information for the external
2236 // references. This is fine because the deoptimizer's code section
2237 // isn't meant to be serialized at all.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002238 CHECK(type == EAGER || type == SOFT || type == LAZY);
2239 DeoptimizerData* data = isolate->deoptimizer_data();
2240 int entry_count = data->deopt_entry_code_entries_[type];
2241 if (max_entry_id < entry_count) return;
2242 entry_count = Max(entry_count, Deoptimizer::kMinNumberOfEntries);
2243 while (max_entry_id >= entry_count) entry_count *= 2;
2244 CHECK(entry_count <= Deoptimizer::kMaxNumberOfEntries);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002245
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002246 MacroAssembler masm(isolate, NULL, 16 * KB, CodeObjectRequired::kYes);
Steve Block44f0eee2011-05-26 01:26:41 +01002247 masm.set_emit_debug_code(false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002248 GenerateDeoptimizationEntries(&masm, entry_count, type);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002249 CodeDesc desc;
2250 masm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002251 DCHECK(!RelocInfo::RequiresRelocation(desc));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002252
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002253 MemoryChunk* chunk = data->deopt_entry_code_[type];
2254 CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >=
2255 desc.instr_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002256 if (!chunk->CommitArea(desc.instr_size)) {
2257 V8::FatalProcessOutOfMemory(
2258 "Deoptimizer::EnsureCodeForDeoptimizationEntry");
2259 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002260 CopyBytes(chunk->area_start(), desc.buffer,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002261 static_cast<size_t>(desc.instr_size));
2262 Assembler::FlushICache(isolate, chunk->area_start(), desc.instr_size);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002263
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002264 data->deopt_entry_code_entries_[type] = entry_count;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002265}
2266
Ben Murdoch097c5b22016-05-18 11:27:45 +01002267FrameDescription::FrameDescription(uint32_t frame_size, int parameter_count)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002268 : frame_size_(frame_size),
Ben Murdoch097c5b22016-05-18 11:27:45 +01002269 parameter_count_(parameter_count),
Ben Murdochb0fe1622011-05-05 13:52:32 +01002270 top_(kZapUint32),
2271 pc_(kZapUint32),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002272 fp_(kZapUint32),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002273 context_(kZapUint32),
2274 constant_pool_(kZapUint32) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002275 // Zap all the registers.
2276 for (int r = 0; r < Register::kNumRegisters; r++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002277 // TODO(jbramley): It isn't safe to use kZapUint32 here. If the register
2278 // isn't used before the next safepoint, the GC will try to scan it as a
2279 // tagged value. kZapUint32 looks like a valid tagged pointer, but it isn't.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002280 SetRegister(r, kZapUint32);
2281 }
2282
2283 // Zap all the slots.
2284 for (unsigned o = 0; o < frame_size; o += kPointerSize) {
2285 SetFrameSlot(o, kZapUint32);
2286 }
2287}
2288
2289
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002290int FrameDescription::ComputeFixedSize() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002291 if (type_ == StackFrame::INTERPRETED) {
2292 return InterpreterFrameConstants::kFixedFrameSize +
Ben Murdoch097c5b22016-05-18 11:27:45 +01002293 parameter_count() * kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002294 } else {
2295 return StandardFrameConstants::kFixedFrameSize +
Ben Murdoch097c5b22016-05-18 11:27:45 +01002296 parameter_count() * kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002297 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002298}
2299
2300
2301unsigned FrameDescription::GetOffsetFromSlotIndex(int slot_index) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002302 if (slot_index >= 0) {
2303 // Local or spill slots. Skip the fixed part of the frame
2304 // including all arguments.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002305 unsigned base = GetFrameSize() - ComputeFixedSize();
Ben Murdochb0fe1622011-05-05 13:52:32 +01002306 return base - ((slot_index + 1) * kPointerSize);
2307 } else {
2308 // Incoming parameter.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002309 int arg_size = parameter_count() * kPointerSize;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002310 unsigned base = GetFrameSize() - arg_size;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002311 return base - ((slot_index + 1) * kPointerSize);
2312 }
2313}
2314
2315
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002316void TranslationBuffer::Add(int32_t value, Zone* zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002317 // This wouldn't handle kMinInt correctly if it ever encountered it.
2318 DCHECK(value != kMinInt);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002319 // Encode the sign bit in the least significant bit.
2320 bool is_negative = (value < 0);
2321 uint32_t bits = ((is_negative ? -value : value) << 1) |
2322 static_cast<int32_t>(is_negative);
2323 // Encode the individual bytes using the least significant bit of
2324 // each byte to indicate whether or not more bytes follow.
2325 do {
2326 uint32_t next = bits >> 7;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002327 contents_.Add(((bits << 1) & 0xFF) | (next != 0), zone);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002328 bits = next;
2329 } while (bits != 0);
2330}
2331
2332
2333int32_t TranslationIterator::Next() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002334 // Run through the bytes until we reach one with a least significant
2335 // bit of zero (marks the end).
2336 uint32_t bits = 0;
2337 for (int i = 0; true; i += 7) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002338 DCHECK(HasNext());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002339 uint8_t next = buffer_->get(index_++);
2340 bits |= (next >> 1) << i;
2341 if ((next & 1) == 0) break;
2342 }
2343 // The bits encode the sign in the least significant bit.
2344 bool is_negative = (bits & 1) == 1;
2345 int32_t result = bits >> 1;
2346 return is_negative ? -result : result;
2347}
2348
2349
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002350Handle<ByteArray> TranslationBuffer::CreateByteArray(Factory* factory) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002351 int length = contents_.length();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002352 Handle<ByteArray> result = factory->NewByteArray(length, TENURED);
2353 MemCopy(result->GetDataStartAddress(), contents_.ToVector().start(), length);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002354 return result;
2355}
2356
2357
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002358void Translation::BeginConstructStubFrame(int literal_id, unsigned height) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002359 buffer_->Add(CONSTRUCT_STUB_FRAME, zone());
2360 buffer_->Add(literal_id, zone());
2361 buffer_->Add(height, zone());
2362}
2363
2364
2365void Translation::BeginGetterStubFrame(int literal_id) {
2366 buffer_->Add(GETTER_STUB_FRAME, zone());
2367 buffer_->Add(literal_id, zone());
2368}
2369
2370
2371void Translation::BeginSetterStubFrame(int literal_id) {
2372 buffer_->Add(SETTER_STUB_FRAME, zone());
2373 buffer_->Add(literal_id, zone());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002374}
2375
2376
2377void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002378 buffer_->Add(ARGUMENTS_ADAPTOR_FRAME, zone());
2379 buffer_->Add(literal_id, zone());
2380 buffer_->Add(height, zone());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002381}
2382
Ben Murdochda12d292016-06-02 14:46:10 +01002383void Translation::BeginTailCallerFrame(int literal_id) {
2384 buffer_->Add(TAIL_CALLER_FRAME, zone());
2385 buffer_->Add(literal_id, zone());
2386}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002387
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002388void Translation::BeginJSFrame(BailoutId node_id,
2389 int literal_id,
2390 unsigned height) {
2391 buffer_->Add(JS_FRAME, zone());
2392 buffer_->Add(node_id.ToInt(), zone());
2393 buffer_->Add(literal_id, zone());
2394 buffer_->Add(height, zone());
2395}
2396
2397
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002398void Translation::BeginInterpretedFrame(BailoutId bytecode_offset,
2399 int literal_id, unsigned height) {
2400 buffer_->Add(INTERPRETED_FRAME, zone());
2401 buffer_->Add(bytecode_offset.ToInt(), zone());
2402 buffer_->Add(literal_id, zone());
2403 buffer_->Add(height, zone());
2404}
2405
2406
2407void Translation::BeginCompiledStubFrame(int height) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002408 buffer_->Add(COMPILED_STUB_FRAME, zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002409 buffer_->Add(height, zone());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002410}
2411
2412
2413void Translation::BeginArgumentsObject(int args_length) {
2414 buffer_->Add(ARGUMENTS_OBJECT, zone());
2415 buffer_->Add(args_length, zone());
2416}
2417
2418
2419void Translation::BeginCapturedObject(int length) {
2420 buffer_->Add(CAPTURED_OBJECT, zone());
2421 buffer_->Add(length, zone());
2422}
2423
2424
2425void Translation::DuplicateObject(int object_index) {
2426 buffer_->Add(DUPLICATED_OBJECT, zone());
2427 buffer_->Add(object_index, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002428}
2429
2430
2431void Translation::StoreRegister(Register reg) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002432 buffer_->Add(REGISTER, zone());
2433 buffer_->Add(reg.code(), zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002434}
2435
2436
2437void Translation::StoreInt32Register(Register reg) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002438 buffer_->Add(INT32_REGISTER, zone());
2439 buffer_->Add(reg.code(), zone());
2440}
2441
2442
2443void Translation::StoreUint32Register(Register reg) {
2444 buffer_->Add(UINT32_REGISTER, zone());
2445 buffer_->Add(reg.code(), zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002446}
2447
2448
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002449void Translation::StoreBoolRegister(Register reg) {
2450 buffer_->Add(BOOL_REGISTER, zone());
2451 buffer_->Add(reg.code(), zone());
2452}
2453
2454
Ben Murdochb0fe1622011-05-05 13:52:32 +01002455void Translation::StoreDoubleRegister(DoubleRegister reg) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002456 buffer_->Add(DOUBLE_REGISTER, zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002457 buffer_->Add(reg.code(), zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002458}
2459
2460
2461void Translation::StoreStackSlot(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002462 buffer_->Add(STACK_SLOT, zone());
2463 buffer_->Add(index, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002464}
2465
2466
2467void Translation::StoreInt32StackSlot(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002468 buffer_->Add(INT32_STACK_SLOT, zone());
2469 buffer_->Add(index, zone());
2470}
2471
2472
2473void Translation::StoreUint32StackSlot(int index) {
2474 buffer_->Add(UINT32_STACK_SLOT, zone());
2475 buffer_->Add(index, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002476}
2477
2478
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002479void Translation::StoreBoolStackSlot(int index) {
2480 buffer_->Add(BOOL_STACK_SLOT, zone());
2481 buffer_->Add(index, zone());
2482}
2483
2484
Ben Murdochb0fe1622011-05-05 13:52:32 +01002485void Translation::StoreDoubleStackSlot(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002486 buffer_->Add(DOUBLE_STACK_SLOT, zone());
2487 buffer_->Add(index, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002488}
2489
2490
2491void Translation::StoreLiteral(int literal_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002492 buffer_->Add(LITERAL, zone());
2493 buffer_->Add(literal_id, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002494}
2495
2496
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002497void Translation::StoreArgumentsObject(bool args_known,
2498 int args_index,
2499 int args_length) {
2500 buffer_->Add(ARGUMENTS_OBJECT, zone());
2501 buffer_->Add(args_known, zone());
2502 buffer_->Add(args_index, zone());
2503 buffer_->Add(args_length, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002504}
2505
2506
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002507void Translation::StoreJSFrameFunction() {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002508 StoreStackSlot((StandardFrameConstants::kCallerPCOffset -
Ben Murdochda12d292016-06-02 14:46:10 +01002509 StandardFrameConstants::kFunctionOffset) /
Ben Murdoch097c5b22016-05-18 11:27:45 +01002510 kPointerSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002511}
2512
Ben Murdochb0fe1622011-05-05 13:52:32 +01002513int Translation::NumberOfOperandsFor(Opcode opcode) {
2514 switch (opcode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002515 case GETTER_STUB_FRAME:
2516 case SETTER_STUB_FRAME:
2517 case DUPLICATED_OBJECT:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002518 case ARGUMENTS_OBJECT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002519 case CAPTURED_OBJECT:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002520 case REGISTER:
2521 case INT32_REGISTER:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002522 case UINT32_REGISTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002523 case BOOL_REGISTER:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002524 case DOUBLE_REGISTER:
2525 case STACK_SLOT:
2526 case INT32_STACK_SLOT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002527 case UINT32_STACK_SLOT:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002528 case BOOL_STACK_SLOT:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002529 case DOUBLE_STACK_SLOT:
2530 case LITERAL:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002531 case COMPILED_STUB_FRAME:
Ben Murdochda12d292016-06-02 14:46:10 +01002532 case TAIL_CALLER_FRAME:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002533 return 1;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002534 case BEGIN:
2535 case ARGUMENTS_ADAPTOR_FRAME:
2536 case CONSTRUCT_STUB_FRAME:
2537 return 2;
2538 case JS_FRAME:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002539 case INTERPRETED_FRAME:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002540 return 3;
2541 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002542 FATAL("Unexpected translation type");
Ben Murdochb0fe1622011-05-05 13:52:32 +01002543 return -1;
2544}
2545
2546
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002547#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002548
2549const char* Translation::StringFor(Opcode opcode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002550#define TRANSLATION_OPCODE_CASE(item) case item: return #item;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002551 switch (opcode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002552 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002553 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002554#undef TRANSLATION_OPCODE_CASE
Ben Murdochb0fe1622011-05-05 13:52:32 +01002555 UNREACHABLE();
2556 return "";
2557}
2558
2559#endif
2560
2561
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002562Handle<FixedArray> MaterializedObjectStore::Get(Address fp) {
2563 int index = StackIdToIndex(fp);
2564 if (index == -1) {
2565 return Handle<FixedArray>::null();
2566 }
2567 Handle<FixedArray> array = GetStackEntries();
2568 CHECK_GT(array->length(), index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002569 return Handle<FixedArray>::cast(Handle<Object>(array->get(index), isolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002570}
2571
2572
2573void MaterializedObjectStore::Set(Address fp,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002574 Handle<FixedArray> materialized_objects) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002575 int index = StackIdToIndex(fp);
2576 if (index == -1) {
2577 index = frame_fps_.length();
2578 frame_fps_.Add(fp);
2579 }
2580
2581 Handle<FixedArray> array = EnsureStackEntries(index + 1);
2582 array->set(index, *materialized_objects);
2583}
2584
2585
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002586bool MaterializedObjectStore::Remove(Address fp) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002587 int index = StackIdToIndex(fp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002588 if (index == -1) {
2589 return false;
2590 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002591 CHECK_GE(index, 0);
2592
2593 frame_fps_.Remove(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002594 FixedArray* array = isolate()->heap()->materialized_objects();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002595 CHECK_LT(index, array->length());
2596 for (int i = index; i < frame_fps_.length(); i++) {
2597 array->set(i, array->get(i + 1));
2598 }
2599 array->set(frame_fps_.length(), isolate()->heap()->undefined_value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002600 return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002601}
2602
2603
2604int MaterializedObjectStore::StackIdToIndex(Address fp) {
2605 for (int i = 0; i < frame_fps_.length(); i++) {
2606 if (frame_fps_[i] == fp) {
2607 return i;
2608 }
2609 }
2610 return -1;
2611}
2612
2613
2614Handle<FixedArray> MaterializedObjectStore::GetStackEntries() {
2615 return Handle<FixedArray>(isolate()->heap()->materialized_objects());
2616}
2617
2618
2619Handle<FixedArray> MaterializedObjectStore::EnsureStackEntries(int length) {
2620 Handle<FixedArray> array = GetStackEntries();
2621 if (array->length() >= length) {
2622 return array;
2623 }
2624
2625 int new_length = length > 10 ? length : 10;
2626 if (new_length < 2 * array->length()) {
2627 new_length = 2 * array->length();
2628 }
2629
2630 Handle<FixedArray> new_array =
2631 isolate()->factory()->NewFixedArray(new_length, TENURED);
2632 for (int i = 0; i < array->length(); i++) {
2633 new_array->set(i, array->get(i));
2634 }
2635 for (int i = array->length(); i < length; i++) {
2636 new_array->set(i, isolate()->heap()->undefined_value());
2637 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002638 isolate()->heap()->SetRootMaterializedObjects(*new_array);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002639 return new_array;
2640}
2641
Ben Murdoch097c5b22016-05-18 11:27:45 +01002642namespace {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002643
Ben Murdoch097c5b22016-05-18 11:27:45 +01002644Handle<Object> GetValueForDebugger(TranslatedFrame::iterator it,
2645 Isolate* isolate) {
2646 if (it->GetRawValue() == isolate->heap()->arguments_marker()) {
2647 if (!it->IsMaterializableByDebugger()) {
2648 return isolate->factory()->undefined_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002649 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002650 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002651 return it->GetValue();
2652}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002653
Ben Murdoch097c5b22016-05-18 11:27:45 +01002654} // namespace
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002655
Ben Murdoch097c5b22016-05-18 11:27:45 +01002656DeoptimizedFrameInfo::DeoptimizedFrameInfo(TranslatedState* state,
2657 TranslatedState::iterator frame_it,
2658 Isolate* isolate) {
2659 // If the previous frame is an adaptor frame, we will take the parameters
2660 // from there.
2661 TranslatedState::iterator parameter_frame = frame_it;
2662 if (parameter_frame != state->begin()) {
2663 parameter_frame--;
2664 }
2665 int parameter_count;
2666 if (parameter_frame->kind() == TranslatedFrame::kArgumentsAdaptor) {
2667 parameter_count = parameter_frame->height() - 1; // Ignore the receiver.
2668 } else {
2669 parameter_frame = frame_it;
2670 parameter_count =
2671 frame_it->shared_info()->internal_formal_parameter_count();
2672 }
2673 TranslatedFrame::iterator parameter_it = parameter_frame->begin();
2674 parameter_it++; // Skip the function.
2675 parameter_it++; // Skip the receiver.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002676
Ben Murdoch097c5b22016-05-18 11:27:45 +01002677 // Figure out whether there is a construct stub frame on top of
2678 // the parameter frame.
2679 has_construct_stub_ =
2680 parameter_frame != state->begin() &&
2681 (parameter_frame - 1)->kind() == TranslatedFrame::kConstructStub;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002682
Ben Murdochc5610432016-08-08 18:44:38 +01002683 source_position_ = Deoptimizer::ComputeSourcePosition(
2684 *frame_it->shared_info(), frame_it->node_id());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002685
2686 TranslatedFrame::iterator value_it = frame_it->begin();
2687 // Get the function. Note that this might materialize the function.
2688 // In case the debugger mutates this value, we should deoptimize
2689 // the function and remember the value in the materialized value store.
2690 function_ = Handle<JSFunction>::cast(value_it->GetValue());
2691
2692 parameters_.resize(static_cast<size_t>(parameter_count));
2693 for (int i = 0; i < parameter_count; i++) {
2694 Handle<Object> parameter = GetValueForDebugger(parameter_it, isolate);
2695 SetParameter(i, parameter);
2696 parameter_it++;
2697 }
2698
2699 // Skip the function, the receiver and the arguments.
2700 int skip_count =
2701 frame_it->shared_info()->internal_formal_parameter_count() + 2;
2702 TranslatedFrame::iterator stack_it = frame_it->begin();
2703 for (int i = 0; i < skip_count; i++) {
2704 stack_it++;
2705 }
2706
2707 // Get the context.
2708 context_ = GetValueForDebugger(stack_it, isolate);
2709 stack_it++;
2710
2711 // Get the expression stack.
2712 int stack_height = frame_it->height();
2713 if (frame_it->kind() == TranslatedFrame::kFunction ||
2714 frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
2715 // For full-code frames, we should not count the context.
2716 // For interpreter frames, we should not count the accumulator.
2717 // TODO(jarin): Clean up the indexing in translated frames.
2718 stack_height--;
2719 }
2720 expression_stack_.resize(static_cast<size_t>(stack_height));
2721 for (int i = 0; i < stack_height; i++) {
2722 Handle<Object> expression = GetValueForDebugger(stack_it, isolate);
2723 SetExpression(i, expression);
2724 stack_it++;
2725 }
2726
2727 // For interpreter frame, skip the accumulator.
2728 if (frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
2729 stack_it++;
2730 }
2731 CHECK(stack_it == frame_it->end());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002732}
2733
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002734
2735const char* Deoptimizer::GetDeoptReason(DeoptReason deopt_reason) {
2736 DCHECK(deopt_reason < kLastDeoptReason);
2737#define DEOPT_MESSAGES_TEXTS(C, T) T,
2738 static const char* deopt_messages_[] = {
2739 DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_TEXTS)};
2740#undef DEOPT_MESSAGES_TEXTS
2741 return deopt_messages_[deopt_reason];
2742}
2743
2744
2745Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code* code, Address pc) {
2746 SourcePosition last_position = SourcePosition::Unknown();
2747 Deoptimizer::DeoptReason last_reason = Deoptimizer::kNoReason;
Ben Murdochc5610432016-08-08 18:44:38 +01002748 int last_deopt_id = Deoptimizer::DeoptInfo::kNoDeoptId;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002749 int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) |
Ben Murdochc5610432016-08-08 18:44:38 +01002750 RelocInfo::ModeMask(RelocInfo::DEOPT_ID) |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002751 RelocInfo::ModeMask(RelocInfo::POSITION);
2752 for (RelocIterator it(code, mask); !it.done(); it.next()) {
2753 RelocInfo* info = it.rinfo();
Ben Murdochc5610432016-08-08 18:44:38 +01002754 if (info->pc() >= pc) {
2755 return DeoptInfo(last_position, last_reason, last_deopt_id);
2756 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002757 if (info->rmode() == RelocInfo::POSITION) {
2758 int raw_position = static_cast<int>(info->data());
2759 last_position = raw_position ? SourcePosition::FromRaw(raw_position)
2760 : SourcePosition::Unknown();
Ben Murdochc5610432016-08-08 18:44:38 +01002761 } else if (info->rmode() == RelocInfo::DEOPT_ID) {
2762 last_deopt_id = static_cast<int>(info->data());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002763 } else if (info->rmode() == RelocInfo::DEOPT_REASON) {
2764 last_reason = static_cast<Deoptimizer::DeoptReason>(info->data());
2765 }
2766 }
Ben Murdochc5610432016-08-08 18:44:38 +01002767 return DeoptInfo(SourcePosition::Unknown(), Deoptimizer::kNoReason, -1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002768}
2769
2770
2771// static
Ben Murdochc5610432016-08-08 18:44:38 +01002772int Deoptimizer::ComputeSourcePosition(SharedFunctionInfo* shared,
2773 BailoutId node_id) {
2774 if (shared->HasBytecodeArray()) {
2775 BytecodeArray* bytecodes = shared->bytecode_array();
2776 // BailoutId points to the next bytecode in the bytecode aray. Subtract
2777 // 1 to get the end of current bytecode.
2778 return bytecodes->SourcePosition(node_id.ToInt() - 1);
2779 } else {
2780 Code* non_optimized_code = shared->code();
2781 FixedArray* raw_data = non_optimized_code->deoptimization_data();
2782 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
2783 unsigned pc_and_state = Deoptimizer::GetOutputInfo(data, node_id, shared);
2784 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
2785 return non_optimized_code->SourcePosition(pc_offset);
2786 }
2787}
2788
2789// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002790TranslatedValue TranslatedValue::NewArgumentsObject(TranslatedState* container,
2791 int length,
2792 int object_index) {
2793 TranslatedValue slot(container, kArgumentsObject);
2794 slot.materialization_info_ = {object_index, length};
2795 return slot;
2796}
2797
2798
2799// static
2800TranslatedValue TranslatedValue::NewDeferredObject(TranslatedState* container,
2801 int length,
2802 int object_index) {
2803 TranslatedValue slot(container, kCapturedObject);
2804 slot.materialization_info_ = {object_index, length};
2805 return slot;
2806}
2807
2808
2809// static
2810TranslatedValue TranslatedValue::NewDuplicateObject(TranslatedState* container,
2811 int id) {
2812 TranslatedValue slot(container, kDuplicatedObject);
2813 slot.materialization_info_ = {id, -1};
2814 return slot;
2815}
2816
2817
2818// static
2819TranslatedValue TranslatedValue::NewDouble(TranslatedState* container,
2820 double value) {
2821 TranslatedValue slot(container, kDouble);
2822 slot.double_value_ = value;
2823 return slot;
2824}
2825
2826
2827// static
2828TranslatedValue TranslatedValue::NewInt32(TranslatedState* container,
2829 int32_t value) {
2830 TranslatedValue slot(container, kInt32);
2831 slot.int32_value_ = value;
2832 return slot;
2833}
2834
2835
2836// static
2837TranslatedValue TranslatedValue::NewUInt32(TranslatedState* container,
2838 uint32_t value) {
2839 TranslatedValue slot(container, kUInt32);
2840 slot.uint32_value_ = value;
2841 return slot;
2842}
2843
2844
2845// static
2846TranslatedValue TranslatedValue::NewBool(TranslatedState* container,
2847 uint32_t value) {
2848 TranslatedValue slot(container, kBoolBit);
2849 slot.uint32_value_ = value;
2850 return slot;
2851}
2852
2853
2854// static
2855TranslatedValue TranslatedValue::NewTagged(TranslatedState* container,
2856 Object* literal) {
2857 TranslatedValue slot(container, kTagged);
2858 slot.raw_literal_ = literal;
2859 return slot;
2860}
2861
2862
2863// static
2864TranslatedValue TranslatedValue::NewInvalid(TranslatedState* container) {
2865 return TranslatedValue(container, kInvalid);
2866}
2867
2868
2869Isolate* TranslatedValue::isolate() const { return container_->isolate(); }
2870
2871
2872Object* TranslatedValue::raw_literal() const {
2873 DCHECK_EQ(kTagged, kind());
2874 return raw_literal_;
2875}
2876
2877
2878int32_t TranslatedValue::int32_value() const {
2879 DCHECK_EQ(kInt32, kind());
2880 return int32_value_;
2881}
2882
2883
2884uint32_t TranslatedValue::uint32_value() const {
2885 DCHECK(kind() == kUInt32 || kind() == kBoolBit);
2886 return uint32_value_;
2887}
2888
2889
2890double TranslatedValue::double_value() const {
2891 DCHECK_EQ(kDouble, kind());
2892 return double_value_;
2893}
2894
2895
2896int TranslatedValue::object_length() const {
2897 DCHECK(kind() == kArgumentsObject || kind() == kCapturedObject);
2898 return materialization_info_.length_;
2899}
2900
2901
2902int TranslatedValue::object_index() const {
2903 DCHECK(kind() == kArgumentsObject || kind() == kCapturedObject ||
2904 kind() == kDuplicatedObject);
2905 return materialization_info_.id_;
2906}
2907
2908
2909Object* TranslatedValue::GetRawValue() const {
2910 // If we have a value, return it.
2911 Handle<Object> result_handle;
2912 if (value_.ToHandle(&result_handle)) {
2913 return *result_handle;
2914 }
2915
2916 // Otherwise, do a best effort to get the value without allocation.
2917 switch (kind()) {
2918 case kTagged:
2919 return raw_literal();
2920
2921 case kInt32: {
2922 bool is_smi = Smi::IsValid(int32_value());
2923 if (is_smi) {
2924 return Smi::FromInt(int32_value());
2925 }
2926 break;
2927 }
2928
2929 case kUInt32: {
2930 bool is_smi = (uint32_value() <= static_cast<uintptr_t>(Smi::kMaxValue));
2931 if (is_smi) {
2932 return Smi::FromInt(static_cast<int32_t>(uint32_value()));
2933 }
2934 break;
2935 }
2936
2937 case kBoolBit: {
2938 if (uint32_value() == 0) {
2939 return isolate()->heap()->false_value();
2940 } else {
2941 CHECK_EQ(1U, uint32_value());
2942 return isolate()->heap()->true_value();
2943 }
2944 }
2945
2946 default:
2947 break;
2948 }
2949
2950 // If we could not get the value without allocation, return the arguments
2951 // marker.
2952 return isolate()->heap()->arguments_marker();
2953}
2954
2955
2956Handle<Object> TranslatedValue::GetValue() {
2957 Handle<Object> result;
2958 // If we already have a value, then get it.
2959 if (value_.ToHandle(&result)) return result;
2960
2961 // Otherwise we have to materialize.
2962 switch (kind()) {
2963 case TranslatedValue::kTagged:
2964 case TranslatedValue::kInt32:
2965 case TranslatedValue::kUInt32:
2966 case TranslatedValue::kBoolBit:
2967 case TranslatedValue::kDouble: {
2968 MaterializeSimple();
2969 return value_.ToHandleChecked();
2970 }
2971
2972 case TranslatedValue::kArgumentsObject:
2973 case TranslatedValue::kCapturedObject:
2974 case TranslatedValue::kDuplicatedObject:
2975 return container_->MaterializeObjectAt(object_index());
2976
2977 case TranslatedValue::kInvalid:
2978 FATAL("unexpected case");
2979 return Handle<Object>::null();
2980 }
2981
2982 FATAL("internal error: value missing");
2983 return Handle<Object>::null();
2984}
2985
2986
2987void TranslatedValue::MaterializeSimple() {
2988 // If we already have materialized, return.
2989 if (!value_.is_null()) return;
2990
2991 Object* raw_value = GetRawValue();
2992 if (raw_value != isolate()->heap()->arguments_marker()) {
2993 // We can get the value without allocation, just return it here.
2994 value_ = Handle<Object>(raw_value, isolate());
2995 return;
2996 }
2997
2998 switch (kind()) {
2999 case kInt32: {
3000 value_ = Handle<Object>(isolate()->factory()->NewNumber(int32_value()));
3001 return;
3002 }
3003
3004 case kUInt32:
3005 value_ = Handle<Object>(isolate()->factory()->NewNumber(uint32_value()));
3006 return;
3007
3008 case kDouble:
3009 value_ = Handle<Object>(isolate()->factory()->NewNumber(double_value()));
3010 return;
3011
3012 case kCapturedObject:
3013 case kDuplicatedObject:
3014 case kArgumentsObject:
3015 case kInvalid:
3016 case kTagged:
3017 case kBoolBit:
3018 FATAL("internal error: unexpected materialization.");
3019 break;
3020 }
3021}
3022
3023
3024bool TranslatedValue::IsMaterializedObject() const {
3025 switch (kind()) {
3026 case kCapturedObject:
3027 case kDuplicatedObject:
3028 case kArgumentsObject:
3029 return true;
3030 default:
3031 return false;
3032 }
3033}
3034
Ben Murdoch097c5b22016-05-18 11:27:45 +01003035bool TranslatedValue::IsMaterializableByDebugger() const {
3036 // At the moment, we only allow materialization of doubles.
3037 return (kind() == kDouble);
3038}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003039
3040int TranslatedValue::GetChildrenCount() const {
3041 if (kind() == kCapturedObject || kind() == kArgumentsObject) {
3042 return object_length();
3043 } else {
3044 return 0;
3045 }
3046}
3047
3048
3049uint32_t TranslatedState::GetUInt32Slot(Address fp, int slot_offset) {
3050 Address address = fp + slot_offset;
3051#if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT
3052 return Memory::uint32_at(address + kIntSize);
3053#else
3054 return Memory::uint32_at(address);
3055#endif
3056}
3057
3058
3059void TranslatedValue::Handlify() {
3060 if (kind() == kTagged) {
3061 value_ = Handle<Object>(raw_literal(), isolate());
3062 raw_literal_ = nullptr;
3063 }
3064}
3065
3066
3067TranslatedFrame TranslatedFrame::JSFrame(BailoutId node_id,
3068 SharedFunctionInfo* shared_info,
3069 int height) {
3070 TranslatedFrame frame(kFunction, shared_info->GetIsolate(), shared_info,
3071 height);
3072 frame.node_id_ = node_id;
3073 return frame;
3074}
3075
3076
3077TranslatedFrame TranslatedFrame::InterpretedFrame(
3078 BailoutId bytecode_offset, SharedFunctionInfo* shared_info, int height) {
3079 TranslatedFrame frame(kInterpretedFunction, shared_info->GetIsolate(),
3080 shared_info, height);
3081 frame.node_id_ = bytecode_offset;
3082 return frame;
3083}
3084
3085
3086TranslatedFrame TranslatedFrame::AccessorFrame(
3087 Kind kind, SharedFunctionInfo* shared_info) {
3088 DCHECK(kind == kSetter || kind == kGetter);
3089 return TranslatedFrame(kind, shared_info->GetIsolate(), shared_info);
3090}
3091
3092
3093TranslatedFrame TranslatedFrame::ArgumentsAdaptorFrame(
3094 SharedFunctionInfo* shared_info, int height) {
3095 return TranslatedFrame(kArgumentsAdaptor, shared_info->GetIsolate(),
3096 shared_info, height);
3097}
3098
Ben Murdochda12d292016-06-02 14:46:10 +01003099TranslatedFrame TranslatedFrame::TailCallerFrame(
3100 SharedFunctionInfo* shared_info) {
3101 return TranslatedFrame(kTailCallerFunction, shared_info->GetIsolate(),
3102 shared_info, 0);
3103}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003104
3105TranslatedFrame TranslatedFrame::ConstructStubFrame(
3106 SharedFunctionInfo* shared_info, int height) {
3107 return TranslatedFrame(kConstructStub, shared_info->GetIsolate(), shared_info,
3108 height);
3109}
3110
3111
3112int TranslatedFrame::GetValueCount() {
3113 switch (kind()) {
3114 case kFunction: {
3115 int parameter_count =
3116 raw_shared_info_->internal_formal_parameter_count() + 1;
3117 // + 1 for function.
3118 return height_ + parameter_count + 1;
3119 }
3120
3121 case kInterpretedFunction: {
3122 int parameter_count =
3123 raw_shared_info_->internal_formal_parameter_count() + 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +01003124 // + 2 for function and context.
3125 return height_ + parameter_count + 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003126 }
3127
3128 case kGetter:
3129 return 2; // Function and receiver.
3130
3131 case kSetter:
3132 return 3; // Function, receiver and the value to set.
3133
3134 case kArgumentsAdaptor:
3135 case kConstructStub:
3136 return 1 + height_;
3137
Ben Murdochda12d292016-06-02 14:46:10 +01003138 case kTailCallerFunction:
3139 return 1; // Function.
3140
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003141 case kCompiledStub:
3142 return height_;
3143
3144 case kInvalid:
3145 UNREACHABLE();
3146 break;
3147 }
3148 UNREACHABLE();
3149 return -1;
3150}
3151
3152
3153void TranslatedFrame::Handlify() {
3154 if (raw_shared_info_ != nullptr) {
3155 shared_info_ = Handle<SharedFunctionInfo>(raw_shared_info_);
3156 raw_shared_info_ = nullptr;
3157 }
3158 for (auto& value : values_) {
3159 value.Handlify();
3160 }
3161}
3162
3163
3164TranslatedFrame TranslatedState::CreateNextTranslatedFrame(
3165 TranslationIterator* iterator, FixedArray* literal_array, Address fp,
3166 FILE* trace_file) {
3167 Translation::Opcode opcode =
3168 static_cast<Translation::Opcode>(iterator->Next());
3169 switch (opcode) {
3170 case Translation::JS_FRAME: {
3171 BailoutId node_id = BailoutId(iterator->Next());
3172 SharedFunctionInfo* shared_info =
3173 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3174 int height = iterator->Next();
3175 if (trace_file != nullptr) {
3176 base::SmartArrayPointer<char> name =
3177 shared_info->DebugName()->ToCString();
3178 PrintF(trace_file, " reading input frame %s", name.get());
3179 int arg_count = shared_info->internal_formal_parameter_count() + 1;
3180 PrintF(trace_file, " => node=%d, args=%d, height=%d; inputs:\n",
3181 node_id.ToInt(), arg_count, height);
3182 }
3183 return TranslatedFrame::JSFrame(node_id, shared_info, height);
3184 }
3185
3186 case Translation::INTERPRETED_FRAME: {
3187 BailoutId bytecode_offset = BailoutId(iterator->Next());
3188 SharedFunctionInfo* shared_info =
3189 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3190 int height = iterator->Next();
3191 if (trace_file != nullptr) {
3192 base::SmartArrayPointer<char> name =
3193 shared_info->DebugName()->ToCString();
3194 PrintF(trace_file, " reading input frame %s", name.get());
3195 int arg_count = shared_info->internal_formal_parameter_count() + 1;
3196 PrintF(trace_file,
3197 " => bytecode_offset=%d, args=%d, height=%d; inputs:\n",
3198 bytecode_offset.ToInt(), arg_count, height);
3199 }
3200 return TranslatedFrame::InterpretedFrame(bytecode_offset, shared_info,
3201 height);
3202 }
3203
3204 case Translation::ARGUMENTS_ADAPTOR_FRAME: {
3205 SharedFunctionInfo* shared_info =
3206 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3207 int height = iterator->Next();
3208 if (trace_file != nullptr) {
3209 base::SmartArrayPointer<char> name =
3210 shared_info->DebugName()->ToCString();
3211 PrintF(trace_file, " reading arguments adaptor frame %s", name.get());
3212 PrintF(trace_file, " => height=%d; inputs:\n", height);
3213 }
3214 return TranslatedFrame::ArgumentsAdaptorFrame(shared_info, height);
3215 }
3216
Ben Murdochda12d292016-06-02 14:46:10 +01003217 case Translation::TAIL_CALLER_FRAME: {
3218 SharedFunctionInfo* shared_info =
3219 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3220 if (trace_file != nullptr) {
3221 base::SmartArrayPointer<char> name =
3222 shared_info->DebugName()->ToCString();
3223 PrintF(trace_file, " reading tail caller frame marker %s\n",
3224 name.get());
3225 }
3226 return TranslatedFrame::TailCallerFrame(shared_info);
3227 }
3228
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003229 case Translation::CONSTRUCT_STUB_FRAME: {
3230 SharedFunctionInfo* shared_info =
3231 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3232 int height = iterator->Next();
3233 if (trace_file != nullptr) {
3234 base::SmartArrayPointer<char> name =
3235 shared_info->DebugName()->ToCString();
3236 PrintF(trace_file, " reading construct stub frame %s", name.get());
3237 PrintF(trace_file, " => height=%d; inputs:\n", height);
3238 }
3239 return TranslatedFrame::ConstructStubFrame(shared_info, height);
3240 }
3241
3242 case Translation::GETTER_STUB_FRAME: {
3243 SharedFunctionInfo* shared_info =
3244 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3245 if (trace_file != nullptr) {
3246 base::SmartArrayPointer<char> name =
3247 shared_info->DebugName()->ToCString();
3248 PrintF(trace_file, " reading getter frame %s; inputs:\n", name.get());
3249 }
3250 return TranslatedFrame::AccessorFrame(TranslatedFrame::kGetter,
3251 shared_info);
3252 }
3253
3254 case Translation::SETTER_STUB_FRAME: {
3255 SharedFunctionInfo* shared_info =
3256 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3257 if (trace_file != nullptr) {
3258 base::SmartArrayPointer<char> name =
3259 shared_info->DebugName()->ToCString();
3260 PrintF(trace_file, " reading setter frame %s; inputs:\n", name.get());
3261 }
3262 return TranslatedFrame::AccessorFrame(TranslatedFrame::kSetter,
3263 shared_info);
3264 }
3265
3266 case Translation::COMPILED_STUB_FRAME: {
3267 int height = iterator->Next();
3268 if (trace_file != nullptr) {
3269 PrintF(trace_file,
3270 " reading compiler stub frame => height=%d; inputs:\n", height);
3271 }
3272 return TranslatedFrame::CompiledStubFrame(height,
3273 literal_array->GetIsolate());
3274 }
3275
3276 case Translation::BEGIN:
3277 case Translation::DUPLICATED_OBJECT:
3278 case Translation::ARGUMENTS_OBJECT:
3279 case Translation::CAPTURED_OBJECT:
3280 case Translation::REGISTER:
3281 case Translation::INT32_REGISTER:
3282 case Translation::UINT32_REGISTER:
3283 case Translation::BOOL_REGISTER:
3284 case Translation::DOUBLE_REGISTER:
3285 case Translation::STACK_SLOT:
3286 case Translation::INT32_STACK_SLOT:
3287 case Translation::UINT32_STACK_SLOT:
3288 case Translation::BOOL_STACK_SLOT:
3289 case Translation::DOUBLE_STACK_SLOT:
3290 case Translation::LITERAL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003291 break;
3292 }
3293 FATAL("We should never get here - unexpected deopt info.");
3294 return TranslatedFrame::InvalidFrame();
3295}
3296
3297
3298// static
3299void TranslatedFrame::AdvanceIterator(
3300 std::deque<TranslatedValue>::iterator* iter) {
3301 int values_to_skip = 1;
3302 while (values_to_skip > 0) {
3303 // Consume the current element.
3304 values_to_skip--;
3305 // Add all the children.
3306 values_to_skip += (*iter)->GetChildrenCount();
3307
3308 (*iter)++;
3309 }
3310}
3311
3312
3313// We can't intermix stack decoding and allocations because
3314// deoptimization infrastracture is not GC safe.
3315// Thus we build a temporary structure in malloced space.
3316TranslatedValue TranslatedState::CreateNextTranslatedValue(
3317 int frame_index, int value_index, TranslationIterator* iterator,
3318 FixedArray* literal_array, Address fp, RegisterValues* registers,
3319 FILE* trace_file) {
3320 disasm::NameConverter converter;
3321
3322 Translation::Opcode opcode =
3323 static_cast<Translation::Opcode>(iterator->Next());
3324 switch (opcode) {
3325 case Translation::BEGIN:
3326 case Translation::JS_FRAME:
3327 case Translation::INTERPRETED_FRAME:
3328 case Translation::ARGUMENTS_ADAPTOR_FRAME:
Ben Murdochda12d292016-06-02 14:46:10 +01003329 case Translation::TAIL_CALLER_FRAME:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003330 case Translation::CONSTRUCT_STUB_FRAME:
3331 case Translation::GETTER_STUB_FRAME:
3332 case Translation::SETTER_STUB_FRAME:
3333 case Translation::COMPILED_STUB_FRAME:
3334 // Peeled off before getting here.
3335 break;
3336
3337 case Translation::DUPLICATED_OBJECT: {
3338 int object_id = iterator->Next();
3339 if (trace_file != nullptr) {
3340 PrintF(trace_file, "duplicated object #%d", object_id);
3341 }
3342 object_positions_.push_back(object_positions_[object_id]);
3343 return TranslatedValue::NewDuplicateObject(this, object_id);
3344 }
3345
3346 case Translation::ARGUMENTS_OBJECT: {
3347 int arg_count = iterator->Next();
3348 int object_index = static_cast<int>(object_positions_.size());
3349 if (trace_file != nullptr) {
3350 PrintF(trace_file, "argumets object #%d (length = %d)", object_index,
3351 arg_count);
3352 }
3353 object_positions_.push_back({frame_index, value_index});
3354 return TranslatedValue::NewArgumentsObject(this, arg_count, object_index);
3355 }
3356
3357 case Translation::CAPTURED_OBJECT: {
3358 int field_count = iterator->Next();
3359 int object_index = static_cast<int>(object_positions_.size());
3360 if (trace_file != nullptr) {
3361 PrintF(trace_file, "captured object #%d (length = %d)", object_index,
3362 field_count);
3363 }
3364 object_positions_.push_back({frame_index, value_index});
3365 return TranslatedValue::NewDeferredObject(this, field_count,
3366 object_index);
3367 }
3368
3369 case Translation::REGISTER: {
3370 int input_reg = iterator->Next();
3371 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3372 intptr_t value = registers->GetRegister(input_reg);
3373 if (trace_file != nullptr) {
3374 PrintF(trace_file, "0x%08" V8PRIxPTR " ; %s ", value,
3375 converter.NameOfCPURegister(input_reg));
3376 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3377 }
3378 return TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value));
3379 }
3380
3381 case Translation::INT32_REGISTER: {
3382 int input_reg = iterator->Next();
3383 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3384 intptr_t value = registers->GetRegister(input_reg);
3385 if (trace_file != nullptr) {
3386 PrintF(trace_file, "%" V8PRIdPTR " ; %s ", value,
3387 converter.NameOfCPURegister(input_reg));
3388 }
3389 return TranslatedValue::NewInt32(this, static_cast<int32_t>(value));
3390 }
3391
3392 case Translation::UINT32_REGISTER: {
3393 int input_reg = iterator->Next();
3394 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3395 intptr_t value = registers->GetRegister(input_reg);
3396 if (trace_file != nullptr) {
3397 PrintF(trace_file, "%" V8PRIuPTR " ; %s (uint)", value,
3398 converter.NameOfCPURegister(input_reg));
3399 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3400 }
3401 return TranslatedValue::NewUInt32(this, static_cast<uint32_t>(value));
3402 }
3403
3404 case Translation::BOOL_REGISTER: {
3405 int input_reg = iterator->Next();
3406 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3407 intptr_t value = registers->GetRegister(input_reg);
3408 if (trace_file != nullptr) {
3409 PrintF(trace_file, "%" V8PRIdPTR " ; %s (bool)", value,
3410 converter.NameOfCPURegister(input_reg));
3411 }
3412 return TranslatedValue::NewBool(this, static_cast<uint32_t>(value));
3413 }
3414
3415 case Translation::DOUBLE_REGISTER: {
3416 int input_reg = iterator->Next();
3417 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3418 double value = registers->GetDoubleRegister(input_reg);
3419 if (trace_file != nullptr) {
3420 PrintF(trace_file, "%e ; %s (bool)", value,
3421 DoubleRegister::from_code(input_reg).ToString());
3422 }
3423 return TranslatedValue::NewDouble(this, value);
3424 }
3425
3426 case Translation::STACK_SLOT: {
3427 int slot_offset =
3428 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3429 intptr_t value = *(reinterpret_cast<intptr_t*>(fp + slot_offset));
3430 if (trace_file != nullptr) {
3431 PrintF(trace_file, "0x%08" V8PRIxPTR " ; [fp %c %d] ", value,
3432 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3433 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3434 }
3435 return TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value));
3436 }
3437
3438 case Translation::INT32_STACK_SLOT: {
3439 int slot_offset =
3440 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3441 uint32_t value = GetUInt32Slot(fp, slot_offset);
3442 if (trace_file != nullptr) {
3443 PrintF(trace_file, "%d ; (int) [fp %c %d] ",
3444 static_cast<int32_t>(value), slot_offset < 0 ? '-' : '+',
3445 std::abs(slot_offset));
3446 }
3447 return TranslatedValue::NewInt32(this, value);
3448 }
3449
3450 case Translation::UINT32_STACK_SLOT: {
3451 int slot_offset =
3452 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3453 uint32_t value = GetUInt32Slot(fp, slot_offset);
3454 if (trace_file != nullptr) {
3455 PrintF(trace_file, "%u ; (uint) [fp %c %d] ", value,
3456 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3457 }
3458 return TranslatedValue::NewUInt32(this, value);
3459 }
3460
3461 case Translation::BOOL_STACK_SLOT: {
3462 int slot_offset =
3463 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3464 uint32_t value = GetUInt32Slot(fp, slot_offset);
3465 if (trace_file != nullptr) {
3466 PrintF(trace_file, "%u ; (bool) [fp %c %d] ", value,
3467 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3468 }
3469 return TranslatedValue::NewBool(this, value);
3470 }
3471
3472 case Translation::DOUBLE_STACK_SLOT: {
3473 int slot_offset =
3474 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3475 double value = ReadDoubleValue(fp + slot_offset);
3476 if (trace_file != nullptr) {
3477 PrintF(trace_file, "%e ; (double) [fp %c %d] ", value,
3478 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3479 }
3480 return TranslatedValue::NewDouble(this, value);
3481 }
3482
3483 case Translation::LITERAL: {
3484 int literal_index = iterator->Next();
3485 Object* value = literal_array->get(literal_index);
3486 if (trace_file != nullptr) {
3487 PrintF(trace_file, "0x%08" V8PRIxPTR " ; (literal %d) ",
3488 reinterpret_cast<intptr_t>(value), literal_index);
3489 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3490 }
3491
3492 return TranslatedValue::NewTagged(this, value);
3493 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003494 }
3495
3496 FATAL("We should never get here - unexpected deopt info.");
3497 return TranslatedValue(nullptr, TranslatedValue::kInvalid);
3498}
3499
3500
3501TranslatedState::TranslatedState(JavaScriptFrame* frame)
3502 : isolate_(nullptr),
3503 stack_frame_pointer_(nullptr),
3504 has_adapted_arguments_(false) {
3505 int deopt_index = Safepoint::kNoDeoptimizationIndex;
3506 DeoptimizationInputData* data =
3507 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
Ben Murdochc5610432016-08-08 18:44:38 +01003508 DCHECK(data != nullptr && deopt_index != Safepoint::kNoDeoptimizationIndex);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003509 TranslationIterator it(data->TranslationByteArray(),
3510 data->TranslationIndex(deopt_index)->value());
3511 Init(frame->fp(), &it, data->LiteralArray(), nullptr /* registers */,
3512 nullptr /* trace file */);
3513}
3514
3515
3516TranslatedState::TranslatedState()
3517 : isolate_(nullptr),
3518 stack_frame_pointer_(nullptr),
3519 has_adapted_arguments_(false) {}
3520
3521
3522void TranslatedState::Init(Address input_frame_pointer,
3523 TranslationIterator* iterator,
3524 FixedArray* literal_array, RegisterValues* registers,
3525 FILE* trace_file) {
3526 DCHECK(frames_.empty());
3527
3528 isolate_ = literal_array->GetIsolate();
3529 // Read out the 'header' translation.
3530 Translation::Opcode opcode =
3531 static_cast<Translation::Opcode>(iterator->Next());
3532 CHECK(opcode == Translation::BEGIN);
3533
3534 int count = iterator->Next();
3535 iterator->Next(); // Drop JS frames count.
3536
3537 frames_.reserve(count);
3538
3539 std::stack<int> nested_counts;
3540
3541 // Read the frames
3542 for (int i = 0; i < count; i++) {
3543 // Read the frame descriptor.
3544 frames_.push_back(CreateNextTranslatedFrame(
3545 iterator, literal_array, input_frame_pointer, trace_file));
3546 TranslatedFrame& frame = frames_.back();
3547
3548 // Read the values.
3549 int values_to_process = frame.GetValueCount();
3550 while (values_to_process > 0 || !nested_counts.empty()) {
3551 if (trace_file != nullptr) {
3552 if (nested_counts.empty()) {
3553 // For top level values, print the value number.
3554 PrintF(trace_file, " %3i: ",
3555 frame.GetValueCount() - values_to_process);
3556 } else {
3557 // Take care of indenting for nested values.
3558 PrintF(trace_file, " ");
3559 for (size_t j = 0; j < nested_counts.size(); j++) {
3560 PrintF(trace_file, " ");
3561 }
3562 }
3563 }
3564
3565 TranslatedValue value = CreateNextTranslatedValue(
3566 i, static_cast<int>(frame.values_.size()), iterator, literal_array,
3567 input_frame_pointer, registers, trace_file);
3568 frame.Add(value);
3569
3570 if (trace_file != nullptr) {
3571 PrintF(trace_file, "\n");
3572 }
3573
3574 // Update the value count and resolve the nesting.
3575 values_to_process--;
3576 int children_count = value.GetChildrenCount();
3577 if (children_count > 0) {
3578 nested_counts.push(values_to_process);
3579 values_to_process = children_count;
3580 } else {
3581 while (values_to_process == 0 && !nested_counts.empty()) {
3582 values_to_process = nested_counts.top();
3583 nested_counts.pop();
3584 }
3585 }
3586 }
3587 }
3588
3589 CHECK(!iterator->HasNext() ||
3590 static_cast<Translation::Opcode>(iterator->Next()) ==
3591 Translation::BEGIN);
3592}
3593
3594
3595void TranslatedState::Prepare(bool has_adapted_arguments,
3596 Address stack_frame_pointer) {
3597 for (auto& frame : frames_) frame.Handlify();
3598
3599 stack_frame_pointer_ = stack_frame_pointer;
3600 has_adapted_arguments_ = has_adapted_arguments;
3601
3602 UpdateFromPreviouslyMaterializedObjects();
3603}
3604
3605
3606Handle<Object> TranslatedState::MaterializeAt(int frame_index,
3607 int* value_index) {
3608 TranslatedFrame* frame = &(frames_[frame_index]);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003609 CHECK(static_cast<size_t>(*value_index) < frame->values_.size());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003610
3611 TranslatedValue* slot = &(frame->values_[*value_index]);
3612 (*value_index)++;
3613
3614 switch (slot->kind()) {
3615 case TranslatedValue::kTagged:
3616 case TranslatedValue::kInt32:
3617 case TranslatedValue::kUInt32:
3618 case TranslatedValue::kBoolBit:
3619 case TranslatedValue::kDouble: {
3620 slot->MaterializeSimple();
3621 Handle<Object> value = slot->GetValue();
3622 if (value->IsMutableHeapNumber()) {
3623 HeapNumber::cast(*value)->set_map(isolate()->heap()->heap_number_map());
3624 }
3625 return value;
3626 }
3627
3628 case TranslatedValue::kArgumentsObject: {
3629 int length = slot->GetChildrenCount();
3630 Handle<JSObject> arguments;
3631 if (GetAdaptedArguments(&arguments, frame_index)) {
3632 // Store the materialized object and consume the nested values.
3633 for (int i = 0; i < length; ++i) {
3634 MaterializeAt(frame_index, value_index);
3635 }
3636 } else {
3637 Handle<JSFunction> function =
3638 Handle<JSFunction>::cast(frame->front().GetValue());
3639 arguments = isolate_->factory()->NewArgumentsObject(function, length);
3640 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
3641 DCHECK_EQ(array->length(), length);
3642 arguments->set_elements(*array);
3643 for (int i = 0; i < length; ++i) {
3644 Handle<Object> value = MaterializeAt(frame_index, value_index);
3645 array->set(i, *value);
3646 }
3647 }
3648 slot->value_ = arguments;
3649 return arguments;
3650 }
3651 case TranslatedValue::kCapturedObject: {
3652 int length = slot->GetChildrenCount();
3653
3654 // The map must be a tagged object.
3655 CHECK(frame->values_[*value_index].kind() == TranslatedValue::kTagged);
3656
3657 Handle<Object> result;
3658 if (slot->value_.ToHandle(&result)) {
3659 // This has been previously materialized, return the previous value.
3660 // We still need to skip all the nested objects.
3661 for (int i = 0; i < length; i++) {
3662 MaterializeAt(frame_index, value_index);
3663 }
3664
3665 return result;
3666 }
3667
3668 Handle<Object> map_object = MaterializeAt(frame_index, value_index);
3669 Handle<Map> map =
3670 Map::GeneralizeAllFieldRepresentations(Handle<Map>::cast(map_object));
3671 switch (map->instance_type()) {
3672 case MUTABLE_HEAP_NUMBER_TYPE:
3673 case HEAP_NUMBER_TYPE: {
3674 // Reuse the HeapNumber value directly as it is already properly
3675 // tagged and skip materializing the HeapNumber explicitly.
3676 Handle<Object> object = MaterializeAt(frame_index, value_index);
3677 slot->value_ = object;
3678 // On 32-bit architectures, there is an extra slot there because
3679 // the escape analysis calculates the number of slots as
3680 // object-size/pointer-size. To account for this, we read out
3681 // any extra slots.
3682 for (int i = 0; i < length - 2; i++) {
3683 MaterializeAt(frame_index, value_index);
3684 }
3685 return object;
3686 }
3687 case JS_OBJECT_TYPE: {
3688 Handle<JSObject> object =
3689 isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED);
3690 slot->value_ = object;
3691 Handle<Object> properties = MaterializeAt(frame_index, value_index);
3692 Handle<Object> elements = MaterializeAt(frame_index, value_index);
3693 object->set_properties(FixedArray::cast(*properties));
3694 object->set_elements(FixedArrayBase::cast(*elements));
3695 for (int i = 0; i < length - 3; ++i) {
3696 Handle<Object> value = MaterializeAt(frame_index, value_index);
3697 FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
3698 object->FastPropertyAtPut(index, *value);
3699 }
3700 return object;
3701 }
3702 case JS_ARRAY_TYPE: {
3703 Handle<JSArray> object =
3704 isolate_->factory()->NewJSArray(0, map->elements_kind());
3705 slot->value_ = object;
3706 Handle<Object> properties = MaterializeAt(frame_index, value_index);
3707 Handle<Object> elements = MaterializeAt(frame_index, value_index);
3708 Handle<Object> length = MaterializeAt(frame_index, value_index);
3709 object->set_properties(FixedArray::cast(*properties));
3710 object->set_elements(FixedArrayBase::cast(*elements));
3711 object->set_length(*length);
3712 return object;
3713 }
3714 case FIXED_ARRAY_TYPE: {
3715 Handle<Object> lengthObject = MaterializeAt(frame_index, value_index);
3716 int32_t length = 0;
3717 CHECK(lengthObject->ToInt32(&length));
3718 Handle<FixedArray> object =
3719 isolate_->factory()->NewFixedArray(length);
3720 // We need to set the map, because the fixed array we are
3721 // materializing could be a context or an arguments object,
3722 // in which case we must retain that information.
3723 object->set_map(*map);
3724 slot->value_ = object;
3725 for (int i = 0; i < length; ++i) {
3726 Handle<Object> value = MaterializeAt(frame_index, value_index);
3727 object->set(i, *value);
3728 }
3729 return object;
3730 }
3731 case FIXED_DOUBLE_ARRAY_TYPE: {
3732 DCHECK_EQ(*map, isolate_->heap()->fixed_double_array_map());
3733 Handle<Object> lengthObject = MaterializeAt(frame_index, value_index);
3734 int32_t length = 0;
3735 CHECK(lengthObject->ToInt32(&length));
3736 Handle<FixedArrayBase> object =
3737 isolate_->factory()->NewFixedDoubleArray(length);
3738 slot->value_ = object;
3739 if (length > 0) {
3740 Handle<FixedDoubleArray> double_array =
3741 Handle<FixedDoubleArray>::cast(object);
3742 for (int i = 0; i < length; ++i) {
3743 Handle<Object> value = MaterializeAt(frame_index, value_index);
3744 CHECK(value->IsNumber());
3745 double_array->set(i, value->Number());
3746 }
3747 }
3748 return object;
3749 }
3750 default:
3751 PrintF(stderr, "[couldn't handle instance type %d]\n",
3752 map->instance_type());
3753 FATAL("unreachable");
3754 return Handle<Object>::null();
3755 }
3756 UNREACHABLE();
3757 break;
3758 }
3759
3760 case TranslatedValue::kDuplicatedObject: {
3761 int object_index = slot->object_index();
3762 TranslatedState::ObjectPosition pos = object_positions_[object_index];
3763
3764 // Make sure the duplicate is refering to a previous object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003765 CHECK(pos.frame_index_ < frame_index ||
3766 (pos.frame_index_ == frame_index &&
3767 pos.value_index_ < *value_index - 1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003768
3769 Handle<Object> object =
3770 frames_[pos.frame_index_].values_[pos.value_index_].GetValue();
3771
3772 // The object should have a (non-sentinel) value.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003773 CHECK(!object.is_null() &&
3774 !object.is_identical_to(isolate_->factory()->arguments_marker()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003775
3776 slot->value_ = object;
3777 return object;
3778 }
3779
3780 case TranslatedValue::kInvalid:
3781 UNREACHABLE();
3782 break;
3783 }
3784
3785 FATAL("We should never get here - unexpected deopt slot kind.");
3786 return Handle<Object>::null();
3787}
3788
3789
3790Handle<Object> TranslatedState::MaterializeObjectAt(int object_index) {
3791 TranslatedState::ObjectPosition pos = object_positions_[object_index];
3792 return MaterializeAt(pos.frame_index_, &(pos.value_index_));
3793}
3794
3795
3796bool TranslatedState::GetAdaptedArguments(Handle<JSObject>* result,
3797 int frame_index) {
3798 if (frame_index == 0) {
3799 // Top level frame -> we need to go to the parent frame on the stack.
3800 if (!has_adapted_arguments_) return false;
3801
3802 // This is top level frame, so we need to go to the stack to get
3803 // this function's argument. (Note that this relies on not inlining
3804 // recursive functions!)
3805 Handle<JSFunction> function =
3806 Handle<JSFunction>::cast(frames_[frame_index].front().GetValue());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003807 *result = Accessors::FunctionGetArguments(function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003808 return true;
3809 } else {
3810 TranslatedFrame* previous_frame = &(frames_[frame_index]);
3811 if (previous_frame->kind() != TranslatedFrame::kArgumentsAdaptor) {
3812 return false;
3813 }
3814 // We get the adapted arguments from the parent translation.
3815 int length = previous_frame->height();
3816 Handle<JSFunction> function =
3817 Handle<JSFunction>::cast(previous_frame->front().GetValue());
3818 Handle<JSObject> arguments =
3819 isolate_->factory()->NewArgumentsObject(function, length);
3820 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
3821 arguments->set_elements(*array);
3822 TranslatedFrame::iterator arg_iterator = previous_frame->begin();
3823 arg_iterator++; // Skip function.
3824 for (int i = 0; i < length; ++i) {
3825 Handle<Object> value = arg_iterator->GetValue();
3826 array->set(i, *value);
3827 arg_iterator++;
3828 }
3829 CHECK(arg_iterator == previous_frame->end());
3830 *result = arguments;
3831 return true;
3832 }
3833}
3834
3835
3836TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex(
3837 int jsframe_index, int* args_count) {
3838 for (size_t i = 0; i < frames_.size(); i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003839 if (frames_[i].kind() == TranslatedFrame::kFunction ||
3840 frames_[i].kind() == TranslatedFrame::kInterpretedFunction) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003841 if (jsframe_index > 0) {
3842 jsframe_index--;
3843 } else {
3844 // We have the JS function frame, now check if it has arguments adaptor.
3845 if (i > 0 &&
3846 frames_[i - 1].kind() == TranslatedFrame::kArgumentsAdaptor) {
3847 *args_count = frames_[i - 1].height();
3848 return &(frames_[i - 1]);
3849 }
3850 *args_count =
3851 frames_[i].shared_info()->internal_formal_parameter_count() + 1;
3852 return &(frames_[i]);
3853 }
3854 }
3855 }
3856 return nullptr;
3857}
3858
3859
3860void TranslatedState::StoreMaterializedValuesAndDeopt() {
3861 MaterializedObjectStore* materialized_store =
3862 isolate_->materialized_object_store();
3863 Handle<FixedArray> previously_materialized_objects =
3864 materialized_store->Get(stack_frame_pointer_);
3865
3866 Handle<Object> marker = isolate_->factory()->arguments_marker();
3867
3868 int length = static_cast<int>(object_positions_.size());
3869 bool new_store = false;
3870 if (previously_materialized_objects.is_null()) {
3871 previously_materialized_objects =
3872 isolate_->factory()->NewFixedArray(length);
3873 for (int i = 0; i < length; i++) {
3874 previously_materialized_objects->set(i, *marker);
3875 }
3876 new_store = true;
3877 }
3878
Ben Murdoch097c5b22016-05-18 11:27:45 +01003879 CHECK_EQ(length, previously_materialized_objects->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003880
3881 bool value_changed = false;
3882 for (int i = 0; i < length; i++) {
3883 TranslatedState::ObjectPosition pos = object_positions_[i];
3884 TranslatedValue* value_info =
3885 &(frames_[pos.frame_index_].values_[pos.value_index_]);
3886
Ben Murdoch097c5b22016-05-18 11:27:45 +01003887 CHECK(value_info->IsMaterializedObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003888
3889 Handle<Object> value(value_info->GetRawValue(), isolate_);
3890
3891 if (!value.is_identical_to(marker)) {
3892 if (previously_materialized_objects->get(i) == *marker) {
3893 previously_materialized_objects->set(i, *value);
3894 value_changed = true;
3895 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003896 CHECK(previously_materialized_objects->get(i) == *value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003897 }
3898 }
3899 }
3900 if (new_store && value_changed) {
3901 materialized_store->Set(stack_frame_pointer_,
3902 previously_materialized_objects);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003903 CHECK(frames_[0].kind() == TranslatedFrame::kFunction ||
Ben Murdochda12d292016-06-02 14:46:10 +01003904 frames_[0].kind() == TranslatedFrame::kInterpretedFunction ||
3905 frames_[0].kind() == TranslatedFrame::kTailCallerFunction);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003906 Object* const function = frames_[0].front().GetRawValue();
3907 Deoptimizer::DeoptimizeFunction(JSFunction::cast(function));
3908 }
3909}
3910
3911
3912void TranslatedState::UpdateFromPreviouslyMaterializedObjects() {
3913 MaterializedObjectStore* materialized_store =
3914 isolate_->materialized_object_store();
3915 Handle<FixedArray> previously_materialized_objects =
3916 materialized_store->Get(stack_frame_pointer_);
3917
3918 // If we have no previously materialized objects, there is nothing to do.
3919 if (previously_materialized_objects.is_null()) return;
3920
3921 Handle<Object> marker = isolate_->factory()->arguments_marker();
3922
3923 int length = static_cast<int>(object_positions_.size());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003924 CHECK_EQ(length, previously_materialized_objects->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003925
3926 for (int i = 0; i < length; i++) {
3927 // For a previously materialized objects, inject their value into the
3928 // translated values.
3929 if (previously_materialized_objects->get(i) != *marker) {
3930 TranslatedState::ObjectPosition pos = object_positions_[i];
3931 TranslatedValue* value_info =
3932 &(frames_[pos.frame_index_].values_[pos.value_index_]);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003933 CHECK(value_info->IsMaterializedObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003934
3935 value_info->value_ =
3936 Handle<Object>(previously_materialized_objects->get(i), isolate_);
3937 }
3938 }
3939}
3940
3941} // namespace internal
3942} // namespace v8