blob: b2c5d42df42b09a82e925939924d0fc2b977cfa8 [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 Murdochb8a8cc12014-11-26 15:28:44 +000050 allocator_->Free(deopt_entry_code_[i]);
51 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 Murdoch3ef787d2012-04-12 10:51:47 +0100231 context = Context::cast(context)->get(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;
299 CHECK(topmost_optimized_code == NULL || safe_to_deopt || turbofanned);
300 if (topmost_optimized_code == NULL) {
301 topmost_optimized_code = code;
302 safe_to_deopt_topmost_optimized_code = safe_to_deopt;
303 }
304 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100305 }
306#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307
308 // Move marked code from the optimized code list to the deoptimized
309 // code list, collecting them into a ZoneList.
Ben Murdochda12d292016-06-02 14:46:10 +0100310 Zone zone(isolate->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000311 ZoneList<Code*> codes(10, &zone);
312
313 // Walk over all optimized code objects in this native context.
314 Code* prev = NULL;
315 Object* element = context->OptimizedCodeListHead();
316 while (!element->IsUndefined()) {
317 Code* code = Code::cast(element);
318 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
319 Object* next = code->next_code_link();
320
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321 if (code->marked_for_deoptimization()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000322 // Put the code into the list for later patching.
323 codes.Add(code, &zone);
324
325 if (prev != NULL) {
326 // Skip this code in the optimized code list.
327 prev->set_next_code_link(next);
328 } else {
329 // There was no previous node, the next node is the new head.
330 context->SetOptimizedCodeListHead(next);
331 }
332
333 // Move the code to the _deoptimized_ code list.
334 code->set_next_code_link(context->DeoptimizedCodeListHead());
335 context->SetDeoptimizedCodeListHead(code);
336 } else {
337 // Not marked; preserve this element.
338 prev = code;
339 }
340 element = next;
341 }
342
Ben Murdoch097c5b22016-05-18 11:27:45 +0100343 // We need a handle scope only because of the macro assembler,
344 // which is used in code patching in EnsureCodeForDeoptimizationEntry.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000345 HandleScope scope(isolate);
346
347 // Now patch all the codes for deoptimization.
348 for (int i = 0; i < codes.length(); i++) {
349#ifdef DEBUG
350 if (codes[i] == topmost_optimized_code) {
351 DCHECK(safe_to_deopt_topmost_optimized_code);
352 }
353#endif
354 // It is finally time to die, code object.
355
356 // Remove the code from optimized code map.
357 DeoptimizationInputData* deopt_data =
358 DeoptimizationInputData::cast(codes[i]->deoptimization_data());
359 SharedFunctionInfo* shared =
360 SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo());
361 shared->EvictFromOptimizedCodeMap(codes[i], "deoptimized code");
362
363 // Do platform-specific patching to force any activations to lazy deopt.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 PatchCodeForDeoptimization(isolate, codes[i]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000365
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 // We might be in the middle of incremental marking with compaction.
367 // Tell collector to treat this code object in a special way and
368 // ignore all slots that might have been recorded on it.
369 isolate->heap()->mark_compact_collector()->InvalidateCode(codes[i]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000370 }
371}
372
373
374void Deoptimizer::DeoptimizeAll(Isolate* isolate) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100375 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
376 TRACE_EVENT0("v8", "V8.DeoptimizeCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377 if (FLAG_trace_deopt) {
378 CodeTracer::Scope scope(isolate->GetCodeTracer());
379 PrintF(scope.file(), "[deoptimize all code in all contexts]\n");
380 }
381 DisallowHeapAllocation no_allocation;
382 // For all contexts, mark all code, then deoptimize.
383 Object* context = isolate->heap()->native_contexts_list();
384 while (!context->IsUndefined()) {
385 Context* native_context = Context::cast(context);
386 MarkAllCodeForContext(native_context);
387 DeoptimizeMarkedCodeForContext(native_context);
388 context = native_context->get(Context::NEXT_CONTEXT_LINK);
389 }
390}
391
392
393void Deoptimizer::DeoptimizeMarkedCode(Isolate* isolate) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100394 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
395 TRACE_EVENT0("v8", "V8.DeoptimizeCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000396 if (FLAG_trace_deopt) {
397 CodeTracer::Scope scope(isolate->GetCodeTracer());
398 PrintF(scope.file(), "[deoptimize marked code in all contexts]\n");
399 }
400 DisallowHeapAllocation no_allocation;
401 // For all contexts, deoptimize code already marked.
402 Object* context = isolate->heap()->native_contexts_list();
403 while (!context->IsUndefined()) {
404 Context* native_context = Context::cast(context);
405 DeoptimizeMarkedCodeForContext(native_context);
406 context = native_context->get(Context::NEXT_CONTEXT_LINK);
407 }
408}
409
410
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000411void Deoptimizer::MarkAllCodeForContext(Context* context) {
412 Object* element = context->OptimizedCodeListHead();
413 while (!element->IsUndefined()) {
414 Code* code = Code::cast(element);
415 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
416 code->set_marked_for_deoptimization(true);
417 element = code->next_code_link();
418 }
419}
420
421
422void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100423 TimerEventScope<TimerEventDeoptimizeCode> timer(function->GetIsolate());
424 TRACE_EVENT0("v8", "V8.DeoptimizeCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425 Code* code = function->code();
426 if (code->kind() == Code::OPTIMIZED_FUNCTION) {
427 // Mark the code for deoptimization and unlink any functions that also
428 // refer to that code. The code cannot be shared across native contexts,
429 // so we only need to search one.
430 code->set_marked_for_deoptimization(true);
431 DeoptimizeMarkedCodeForContext(function->context()->native_context());
432 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100433}
434
435
Ben Murdoch8b112d22011-06-08 16:22:53 +0100436void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100437 deoptimizer->DoComputeOutputFrames();
438}
439
440
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000441bool Deoptimizer::TraceEnabledFor(BailoutType deopt_type,
442 StackFrame::Type frame_type) {
443 switch (deopt_type) {
444 case EAGER:
445 case SOFT:
446 case LAZY:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000447 return (frame_type == StackFrame::STUB)
448 ? FLAG_trace_stub_failures
449 : FLAG_trace_deopt;
450 }
451 FATAL("Unsupported deopt type");
452 return false;
453}
454
455
456const char* Deoptimizer::MessageFor(BailoutType type) {
457 switch (type) {
458 case EAGER: return "eager";
459 case SOFT: return "soft";
460 case LAZY: return "lazy";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000461 }
462 FATAL("Unsupported deopt type");
463 return NULL;
464}
465
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function,
467 BailoutType type, unsigned bailout_id, Address from,
468 int fp_to_sp_delta, Code* optimized_code)
Steve Block44f0eee2011-05-26 01:26:41 +0100469 : isolate_(isolate),
470 function_(function),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100471 bailout_id_(bailout_id),
472 bailout_type_(type),
473 from_(from),
474 fp_to_sp_delta_(fp_to_sp_delta),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100475 deoptimizing_throw_(false),
476 catch_handler_data_(-1),
477 catch_handler_pc_offset_(-1),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478 input_(nullptr),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100479 output_count_(0),
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100480 jsframe_count_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000481 output_(nullptr),
Ben Murdochda12d292016-06-02 14:46:10 +0100482 caller_frame_top_(0),
483 caller_fp_(0),
484 caller_pc_(0),
485 caller_constant_pool_(0),
486 input_frame_context_(0),
487 stack_fp_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 trace_scope_(nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100489 if (isolate->deoptimizer_lazy_throw()) {
490 isolate->set_deoptimizer_lazy_throw(false);
491 deoptimizing_throw_ = true;
492 }
493
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494 // For COMPILED_STUBs called from builtins, the function pointer is a SMI
495 // indicating an internal frame.
496 if (function->IsSmi()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 function = nullptr;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100498 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000499 DCHECK(from != nullptr);
500 if (function != nullptr && function->IsOptimized()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000501 function->shared()->increment_deopt_count();
502 if (bailout_type_ == Deoptimizer::SOFT) {
503 isolate->counters()->soft_deopts_executed()->Increment();
504 // Soft deopts shouldn't count against the overall re-optimization count
505 // that can eventually lead to disabling optimization for a function.
506 int opt_count = function->shared()->opt_count();
507 if (opt_count > 0) opt_count--;
508 function->shared()->set_opt_count(opt_count);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100509 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100510 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511 compiled_code_ = FindOptimizedCode(function, optimized_code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000512#if DEBUG
513 DCHECK(compiled_code_ != NULL);
514 if (type == EAGER || type == SOFT || type == LAZY) {
515 DCHECK(compiled_code_->kind() != Code::FUNCTION);
516 }
517#endif
518
519 StackFrame::Type frame_type = function == NULL
520 ? StackFrame::STUB
521 : StackFrame::JAVA_SCRIPT;
522 trace_scope_ = TraceEnabledFor(type, frame_type) ?
523 new CodeTracer::Scope(isolate->GetCodeTracer()) : NULL;
524#ifdef DEBUG
525 CHECK(AllowHeapAllocation::IsAllowed());
526 disallow_heap_allocation_ = new DisallowHeapAllocation();
527#endif // DEBUG
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000528 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
529 PROFILE(isolate_, CodeDeoptEvent(compiled_code_, from_, fp_to_sp_delta_));
530 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100531 unsigned size = ComputeInputFrameSize();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100532 int parameter_count =
533 function == nullptr
534 ? 0
535 : (function->shared()->internal_formal_parameter_count() + 1);
536 input_ = new (size) FrameDescription(size, parameter_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000537 input_->SetFrameType(frame_type);
538}
539
540
541Code* Deoptimizer::FindOptimizedCode(JSFunction* function,
542 Code* optimized_code) {
543 switch (bailout_type_) {
544 case Deoptimizer::SOFT:
545 case Deoptimizer::EAGER:
546 case Deoptimizer::LAZY: {
547 Code* compiled_code = FindDeoptimizingCode(from_);
548 return (compiled_code == NULL)
549 ? static_cast<Code*>(isolate_->FindCodeObject(from_))
550 : compiled_code;
551 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552 }
553 FATAL("Could not find code for optimized function");
554 return NULL;
555}
556
557
558void Deoptimizer::PrintFunctionName() {
559 if (function_->IsJSFunction()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400560 function_->ShortPrint(trace_scope_->file());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000561 } else {
562 PrintF(trace_scope_->file(),
563 "%s", Code::Kind2String(compiled_code_->kind()));
564 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100565}
566
567
568Deoptimizer::~Deoptimizer() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000569 DCHECK(input_ == NULL && output_ == NULL);
570 DCHECK(disallow_heap_allocation_ == NULL);
571 delete trace_scope_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100572}
573
574
575void Deoptimizer::DeleteFrameDescriptions() {
576 delete input_;
577 for (int i = 0; i < output_count_; ++i) {
578 if (output_[i] != input_) delete output_[i];
579 }
580 delete[] output_;
581 input_ = NULL;
582 output_ = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583#ifdef DEBUG
584 CHECK(!AllowHeapAllocation::IsAllowed());
585 CHECK(disallow_heap_allocation_ != NULL);
586 delete disallow_heap_allocation_;
587 disallow_heap_allocation_ = NULL;
588#endif // DEBUG
Ben Murdochb0fe1622011-05-05 13:52:32 +0100589}
590
591
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate,
593 int id,
594 BailoutType type,
595 GetEntryMode mode) {
596 CHECK_GE(id, 0);
597 if (id >= kMaxNumberOfEntries) return NULL;
598 if (mode == ENSURE_ENTRY_CODE) {
599 EnsureCodeForDeoptimizationEntry(isolate, type, id);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100600 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601 CHECK_EQ(mode, CALCULATE_ENTRY_ADDRESS);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100602 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000603 DeoptimizerData* data = isolate->deoptimizer_data();
Ben Murdochda12d292016-06-02 14:46:10 +0100604 CHECK_LE(type, kLastBailoutType);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605 MemoryChunk* base = data->deopt_entry_code_[type];
606 return base->area_start() + (id * table_entry_size_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100607}
608
609
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000610int Deoptimizer::GetDeoptimizationId(Isolate* isolate,
611 Address addr,
612 BailoutType type) {
613 DeoptimizerData* data = isolate->deoptimizer_data();
614 MemoryChunk* base = data->deopt_entry_code_[type];
615 Address start = base->area_start();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400616 if (addr < start ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000617 addr >= start + (kMaxNumberOfEntries * table_entry_size_)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100618 return kNotDeoptimizationEntry;
619 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000620 DCHECK_EQ(0,
621 static_cast<int>(addr - start) % table_entry_size_);
622 return static_cast<int>(addr - start) / table_entry_size_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100623}
624
625
Steve Block9fac8402011-05-12 15:51:54 +0100626int Deoptimizer::GetOutputInfo(DeoptimizationOutputData* data,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000627 BailoutId id,
Steve Block9fac8402011-05-12 15:51:54 +0100628 SharedFunctionInfo* shared) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100629 // TODO(kasperl): For now, we do a simple linear search for the PC
630 // offset associated with the given node id. This should probably be
631 // changed to a binary search.
632 int length = data->DeoptPoints();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100633 for (int i = 0; i < length; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000634 if (data->AstId(i) == id) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100635 return data->PcAndState(i)->value();
636 }
637 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000638 OFStream os(stderr);
639 os << "[couldn't find pc offset for node=" << id.ToInt() << "]\n"
640 << "[method: " << shared->DebugName()->ToCString().get() << "]\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400641 << "[source:\n" << SourceCodeOf(shared) << "\n]" << std::endl;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100642
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000643 shared->GetHeap()->isolate()->PushStackTraceAndDie(0xfefefefe, data, shared,
644 0xfefefeff);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000645 FATAL("unable to find pc offset during deoptimization");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100646 return -1;
647}
648
649
Steve Block44f0eee2011-05-26 01:26:41 +0100650int Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100651 int length = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000652 // Count all entries in the deoptimizing code list of every context.
653 Object* context = isolate->heap()->native_contexts_list();
654 while (!context->IsUndefined()) {
655 Context* native_context = Context::cast(context);
656 Object* element = native_context->DeoptimizedCodeListHead();
657 while (!element->IsUndefined()) {
658 Code* code = Code::cast(element);
659 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
660 length++;
661 element = code->next_code_link();
662 }
663 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100664 }
665 return length;
666}
667
Ben Murdoch097c5b22016-05-18 11:27:45 +0100668namespace {
669
670int LookupCatchHandler(TranslatedFrame* translated_frame, int* data_out) {
671 switch (translated_frame->kind()) {
672 case TranslatedFrame::kFunction: {
673 BailoutId node_id = translated_frame->node_id();
674 JSFunction* function =
675 JSFunction::cast(translated_frame->begin()->GetRawValue());
676 Code* non_optimized_code = function->shared()->code();
677 FixedArray* raw_data = non_optimized_code->deoptimization_data();
678 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
679 unsigned pc_and_state =
680 Deoptimizer::GetOutputInfo(data, node_id, function->shared());
681 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
682 HandlerTable* table =
683 HandlerTable::cast(non_optimized_code->handler_table());
684 HandlerTable::CatchPrediction prediction;
685 return table->LookupRange(pc_offset, data_out, &prediction);
686 }
687 case TranslatedFrame::kInterpretedFunction: {
688 int bytecode_offset = translated_frame->node_id().ToInt();
689 JSFunction* function =
690 JSFunction::cast(translated_frame->begin()->GetRawValue());
691 BytecodeArray* bytecode = function->shared()->bytecode_array();
692 HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
693 HandlerTable::CatchPrediction prediction;
694 return table->LookupRange(bytecode_offset, data_out, &prediction);
695 }
696 default:
697 break;
698 }
699 return -1;
700}
701
702} // namespace
Ben Murdochb0fe1622011-05-05 13:52:32 +0100703
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100704// We rely on this function not causing a GC. It is called from generated code
705// without having a real stack frame in place.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100706void Deoptimizer::DoComputeOutputFrames() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000707 base::ElapsedTimer timer;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100708
709 // Determine basic deoptimization information. The optimized frame is
710 // described by the input data.
711 DeoptimizationInputData* input_data =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000712 DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
713
Ben Murdochda12d292016-06-02 14:46:10 +0100714 {
715 // Read caller's PC, caller's FP and caller's constant pool values
716 // from input frame. Compute caller's frame top address.
717
718 Register fp_reg = JavaScriptFrame::fp_register();
719 stack_fp_ = input_->GetRegister(fp_reg.code());
720
721 caller_frame_top_ = stack_fp_ + ComputeInputFrameAboveFpFixedSize();
722
723 Address fp_address = input_->GetFramePointerAddress();
724 caller_fp_ = Memory::intptr_at(fp_address);
725 caller_pc_ =
726 Memory::intptr_at(fp_address + CommonFrameConstants::kCallerPCOffset);
727 input_frame_context_ = Memory::intptr_at(
728 fp_address + CommonFrameConstants::kContextOrFrameTypeOffset);
729
730 if (FLAG_enable_embedded_constant_pool) {
731 caller_constant_pool_ = Memory::intptr_at(
732 fp_address + CommonFrameConstants::kConstantPoolOffset);
733 }
734 }
735
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000736 if (trace_scope_ != NULL) {
737 timer.Start();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400738 PrintF(trace_scope_->file(), "[deoptimizing (DEOPT %s): begin ",
739 MessageFor(bailout_type_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000740 PrintFunctionName();
741 PrintF(trace_scope_->file(),
Ben Murdochda12d292016-06-02 14:46:10 +0100742 " (opt #%d) @%d, FP to SP delta: %d, caller sp: 0x%08" V8PRIxPTR
743 "]\n",
744 input_data->OptimizationId()->value(), bailout_id_, fp_to_sp_delta_,
745 caller_frame_top_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746 if (bailout_type_ == EAGER || bailout_type_ == SOFT ||
747 (compiled_code_->is_hydrogen_stub())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000748 compiled_code_->PrintDeoptLocation(trace_scope_->file(), from_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000749 }
750 }
751
752 BailoutId node_id = input_data->AstId(bailout_id_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100753 ByteArray* translations = input_data->TranslationByteArray();
754 unsigned translation_index =
755 input_data->TranslationIndex(bailout_id_)->value();
756
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000757 TranslationIterator state_iterator(translations, translation_index);
758 translated_state_.Init(
759 input_->GetFramePointerAddress(), &state_iterator,
760 input_data->LiteralArray(), input_->GetRegisterValues(),
761 trace_scope_ == nullptr ? nullptr : trace_scope_->file());
762
Ben Murdochb0fe1622011-05-05 13:52:32 +0100763 // Do the input frame to output frame(s) translation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000764 size_t count = translated_state_.frames().size();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100765 // If we are supposed to go to the catch handler, find the catching frame
766 // for the catch and make sure we only deoptimize upto that frame.
767 if (deoptimizing_throw_) {
768 size_t catch_handler_frame_index = count;
769 for (size_t i = count; i-- > 0;) {
770 catch_handler_pc_offset_ = LookupCatchHandler(
771 &(translated_state_.frames()[i]), &catch_handler_data_);
772 if (catch_handler_pc_offset_ >= 0) {
773 catch_handler_frame_index = i;
774 break;
775 }
776 }
777 CHECK_LT(catch_handler_frame_index, count);
778 count = catch_handler_frame_index + 1;
779 }
780
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000781 DCHECK(output_ == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100782 output_ = new FrameDescription*[count];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000783 for (size_t i = 0; i < count; ++i) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100784 output_[i] = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100785 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000786 output_count_ = static_cast<int>(count);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100787
788 // Translate each output frame.
Ben Murdochda12d292016-06-02 14:46:10 +0100789 int frame_index = 0; // output_frame_index
790 for (size_t i = 0; i < count; ++i, ++frame_index) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100791 // Read the ast node id, function, and frame height for this output frame.
Ben Murdochda12d292016-06-02 14:46:10 +0100792 TranslatedFrame* translated_frame = &(translated_state_.frames()[i]);
793 switch (translated_frame->kind()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000794 case TranslatedFrame::kFunction:
Ben Murdochda12d292016-06-02 14:46:10 +0100795 DoComputeJSFrame(translated_frame, frame_index,
796 deoptimizing_throw_ && i == count - 1);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100797 jsframe_count_++;
798 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000799 case TranslatedFrame::kInterpretedFunction:
Ben Murdochda12d292016-06-02 14:46:10 +0100800 DoComputeInterpretedFrame(translated_frame, frame_index,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100801 deoptimizing_throw_ && i == count - 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802 jsframe_count_++;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100803 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000804 case TranslatedFrame::kArgumentsAdaptor:
Ben Murdochda12d292016-06-02 14:46:10 +0100805 DoComputeArgumentsAdaptorFrame(translated_frame, frame_index);
806 break;
807 case TranslatedFrame::kTailCallerFunction:
808 DoComputeTailCallerFrame(translated_frame, frame_index);
809 // Tail caller frame translations do not produce output frames.
810 frame_index--;
811 output_count_--;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100812 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000813 case TranslatedFrame::kConstructStub:
Ben Murdochda12d292016-06-02 14:46:10 +0100814 DoComputeConstructStubFrame(translated_frame, frame_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000815 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000816 case TranslatedFrame::kGetter:
Ben Murdochda12d292016-06-02 14:46:10 +0100817 DoComputeAccessorStubFrame(translated_frame, frame_index, false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000818 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000819 case TranslatedFrame::kSetter:
Ben Murdochda12d292016-06-02 14:46:10 +0100820 DoComputeAccessorStubFrame(translated_frame, frame_index, true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000821 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000822 case TranslatedFrame::kCompiledStub:
Ben Murdochda12d292016-06-02 14:46:10 +0100823 DoComputeCompiledStubFrame(translated_frame, frame_index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000824 break;
825 case TranslatedFrame::kInvalid:
826 FATAL("invalid frame");
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100827 break;
828 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100829 }
830
831 // Print some helpful diagnostic information.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000832 if (trace_scope_ != NULL) {
833 double ms = timer.Elapsed().InMillisecondsF();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100834 int index = output_count_ - 1; // Index of the topmost frame.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400835 PrintF(trace_scope_->file(), "[deoptimizing (%s): end ",
836 MessageFor(bailout_type_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000837 PrintFunctionName();
838 PrintF(trace_scope_->file(),
Ben Murdochda12d292016-06-02 14:46:10 +0100839 " @%d => node=%d, pc=0x%08" V8PRIxPTR ", caller sp=0x%08" V8PRIxPTR
840 ", state=%s, took %0.3f ms]\n",
841 bailout_id_, node_id.ToInt(), output_[index]->GetPc(),
842 caller_frame_top_, FullCodeGenerator::State2String(
843 static_cast<FullCodeGenerator::State>(
844 output_[index]->GetState()->value())),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100845 ms);
846 }
847}
848
Ben Murdochda12d292016-06-02 14:46:10 +0100849void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame,
850 int frame_index, bool goto_catch_handler) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100851 SharedFunctionInfo* shared = translated_frame->raw_shared_info();
852
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853 TranslatedFrame::iterator value_iterator = translated_frame->begin();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100854 bool is_bottommost = (0 == frame_index);
855 bool is_topmost = (output_count_ - 1 == frame_index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000856 int input_index = 0;
857
858 BailoutId node_id = translated_frame->node_id();
859 unsigned height =
860 translated_frame->height() - 1; // Do not count the context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000861 unsigned height_in_bytes = height * kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100862 if (goto_catch_handler) {
863 // Take the stack height from the handler table.
864 height = catch_handler_data_;
865 // We also make space for the exception itself.
866 height_in_bytes = (height + 1) * kPointerSize;
867 CHECK(is_topmost);
868 }
869
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000870 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
871 value_iterator++;
872 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000873 if (trace_scope_ != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000874 PrintF(trace_scope_->file(), " translating frame ");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100875 base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
876 PrintF(trace_scope_->file(), "%s", name.get());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100877 PrintF(trace_scope_->file(), " => node=%d, height=%d%s\n", node_id.ToInt(),
878 height_in_bytes, goto_catch_handler ? " (throw)" : "");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000879 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100880
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000881 // The 'fixed' part of the frame consists of the incoming parameters and
882 // the part described by JavaScriptFrameConstants.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100883 unsigned fixed_frame_size = ComputeJavascriptFixedSize(shared);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000884 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
885
886 // Allocate and store the output frame description.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100887 int parameter_count = shared->internal_formal_parameter_count() + 1;
888 FrameDescription* output_frame = new (output_frame_size)
889 FrameDescription(output_frame_size, parameter_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000890 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
891
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000892 CHECK(frame_index >= 0 && frame_index < output_count_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000893 CHECK_NULL(output_[frame_index]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000894 output_[frame_index] = output_frame;
895
Ben Murdochda12d292016-06-02 14:46:10 +0100896 // The top address of the frame is computed from the previous frame's top and
897 // this frame's size.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000898 intptr_t top_address;
899 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +0100900 top_address = caller_frame_top_ - output_frame_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000901 } else {
902 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
903 }
904 output_frame->SetTop(top_address);
905
906 // Compute the incoming parameter translation.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000907 unsigned output_offset = output_frame_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000908 for (int i = 0; i < parameter_count; ++i) {
909 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000910 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
911 output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000912 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000913
914 // There are no translation commands for the caller's pc and fp, the
915 // context, and the function. Synthesize their values and set them up
916 // explicitly.
917 //
918 // The caller's pc for the bottommost output frame is the same as in the
919 // input frame. For all subsequent output frames, it can be read from the
920 // previous one. This frame's pc can be computed from the non-optimized
921 // function code and AST id of the bailout.
922 output_offset -= kPCOnStackSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923 intptr_t value;
924 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +0100925 value = caller_pc_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000926 } else {
927 value = output_[frame_index - 1]->GetPc();
928 }
929 output_frame->SetCallerPc(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000930 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000931
932 // The caller's frame pointer for the bottommost output frame is the same
933 // as in the input frame. For all subsequent output frames, it can be
934 // read from the previous one. Also compute and set this frame's frame
935 // pointer.
936 output_offset -= kFPOnStackSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000937 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +0100938 value = caller_fp_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000939 } else {
940 value = output_[frame_index - 1]->GetFp();
941 }
942 output_frame->SetCallerFp(output_offset, value);
943 intptr_t fp_value = top_address + output_offset;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000944 output_frame->SetFp(fp_value);
Ben Murdochda12d292016-06-02 14:46:10 +0100945 if (is_topmost) {
946 Register fp_reg = JavaScriptFrame::fp_register();
947 output_frame->SetRegister(fp_reg.code(), fp_value);
948 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000949 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000950
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000952 // For the bottommost output frame the constant pool pointer can be gotten
953 // from the input frame. For subsequent output frames, it can be read from
954 // the previous frame.
955 output_offset -= kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000956 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +0100957 value = caller_constant_pool_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000958 } else {
959 value = output_[frame_index - 1]->GetConstantPool();
960 }
961 output_frame->SetCallerConstantPool(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000962 DebugPrintOutputSlot(value, frame_index, output_offset,
963 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000964 }
965
966 // For the bottommost output frame the context can be gotten from the input
967 // frame. For all subsequent output frames it can be gotten from the function
968 // so long as we don't inline functions that need local contexts.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000969 output_offset -= kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100970
971 TranslatedFrame::iterator context_pos = value_iterator;
972 int context_input_index = input_index;
973 // When deoptimizing into a catch block, we need to take the context
974 // from just above the top of the operand stack (we push the context
975 // at the entry of the try block).
976 if (goto_catch_handler) {
977 for (unsigned i = 0; i < height + 1; ++i) {
978 context_pos++;
979 context_input_index++;
980 }
981 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000982 // Read the context from the translations.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100983 Object* context = context_pos->GetRawValue();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000984 if (context == isolate_->heap()->undefined_value()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000985 // If the context was optimized away, just use the context from
986 // the activation. This should only apply to Crankshaft code.
987 CHECK(!compiled_code_->is_turbofanned());
Ben Murdochda12d292016-06-02 14:46:10 +0100988 context = is_bottommost ? reinterpret_cast<Object*>(input_frame_context_)
989 : function->context();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000990 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000991 value = reinterpret_cast<intptr_t>(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000992 output_frame->SetContext(value);
Ben Murdochda12d292016-06-02 14:46:10 +0100993 if (is_topmost) {
994 Register context_reg = JavaScriptFrame::context_register();
995 output_frame->SetRegister(context_reg.code(), value);
996 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100997 WriteValueToOutput(context, context_input_index, frame_index, output_offset,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000998 "context ");
999 if (context == isolate_->heap()->arguments_marker()) {
1000 Address output_address =
1001 reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
1002 output_offset;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001003 values_to_materialize_.push_back({output_address, context_pos});
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001004 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 value_iterator++;
1006 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001007
1008 // The function was mentioned explicitly in the BEGIN_FRAME.
1009 output_offset -= kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001010 value = reinterpret_cast<intptr_t>(function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011 WriteValueToOutput(function, 0, frame_index, output_offset, "function ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001012
1013 // Translate the rest of the frame.
1014 for (unsigned i = 0; i < height; ++i) {
1015 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001016 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1017 output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001018 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001019 if (goto_catch_handler) {
1020 // Write out the exception for the catch handler.
1021 output_offset -= kPointerSize;
1022 Object* exception_obj = reinterpret_cast<Object*>(
1023 input_->GetRegister(FullCodeGenerator::result_register().code()));
1024 WriteValueToOutput(exception_obj, input_index, frame_index, output_offset,
1025 "exception ");
1026 input_index++;
1027 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001028 CHECK_EQ(0u, output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001029
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001030 // Update constant pool.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001031 Code* non_optimized_code = shared->code();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001032 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001033 intptr_t constant_pool_value =
1034 reinterpret_cast<intptr_t>(non_optimized_code->constant_pool());
1035 output_frame->SetConstantPool(constant_pool_value);
1036 if (is_topmost) {
1037 Register constant_pool_reg =
1038 JavaScriptFrame::constant_pool_pointer_register();
1039 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
1040 }
1041 }
1042
Ben Murdoch097c5b22016-05-18 11:27:45 +01001043 // Compute this frame's PC, state, and continuation.
1044 FixedArray* raw_data = non_optimized_code->deoptimization_data();
1045 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
1046 Address start = non_optimized_code->instruction_start();
1047 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared());
1048 unsigned pc_offset = goto_catch_handler
1049 ? catch_handler_pc_offset_
1050 : FullCodeGenerator::PcField::decode(pc_and_state);
1051 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset);
1052 output_frame->SetPc(pc_value);
1053
1054 // If we are going to the catch handler, then the exception lives in
1055 // the accumulator.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001056 FullCodeGenerator::State state =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001057 goto_catch_handler ? FullCodeGenerator::TOS_REG
1058 : FullCodeGenerator::StateField::decode(pc_and_state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001059 output_frame->SetState(Smi::FromInt(state));
1060
1061 // Set the continuation for the topmost frame.
Ben Murdochda12d292016-06-02 14:46:10 +01001062 if (is_topmost) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001063 Builtins* builtins = isolate_->builtins();
1064 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
1065 if (bailout_type_ == LAZY) {
1066 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
1067 } else if (bailout_type_ == SOFT) {
1068 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized);
1069 } else {
1070 CHECK_EQ(bailout_type_, EAGER);
1071 }
1072 output_frame->SetContinuation(
1073 reinterpret_cast<intptr_t>(continuation->entry()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001074 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001075}
1076
Ben Murdochda12d292016-06-02 14:46:10 +01001077void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
1078 int frame_index,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001079 bool goto_catch_handler) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001080 SharedFunctionInfo* shared = translated_frame->raw_shared_info();
1081
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001082 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1083 int input_index = 0;
1084
Ben Murdoch097c5b22016-05-18 11:27:45 +01001085 int bytecode_offset = translated_frame->node_id().ToInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001086 unsigned height = translated_frame->height();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001087 unsigned height_in_bytes = height * kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001088 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
1089 value_iterator++;
1090 input_index++;
1091 if (trace_scope_ != NULL) {
1092 PrintF(trace_scope_->file(), " translating interpreted frame ");
Ben Murdoch097c5b22016-05-18 11:27:45 +01001093 base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
1094 PrintF(trace_scope_->file(), "%s", name.get());
1095 PrintF(trace_scope_->file(), " => bytecode_offset=%d, height=%d%s\n",
1096 bytecode_offset, height_in_bytes,
1097 goto_catch_handler ? " (throw)" : "");
1098 }
1099 if (goto_catch_handler) {
1100 bytecode_offset = catch_handler_pc_offset_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001101 }
1102
1103 // The 'fixed' part of the frame consists of the incoming parameters and
1104 // the part described by InterpreterFrameConstants.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001105 unsigned fixed_frame_size = ComputeInterpretedFixedSize(shared);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001106 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1107
1108 // Allocate and store the output frame description.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001109 int parameter_count = shared->internal_formal_parameter_count() + 1;
1110 FrameDescription* output_frame = new (output_frame_size)
1111 FrameDescription(output_frame_size, parameter_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001112 output_frame->SetFrameType(StackFrame::INTERPRETED);
1113
1114 bool is_bottommost = (0 == frame_index);
1115 bool is_topmost = (output_count_ - 1 == frame_index);
1116 CHECK(frame_index >= 0 && frame_index < output_count_);
1117 CHECK_NULL(output_[frame_index]);
1118 output_[frame_index] = output_frame;
1119
Ben Murdochda12d292016-06-02 14:46:10 +01001120 // The top address of the frame is computed from the previous frame's top and
1121 // this frame's size.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001122 intptr_t top_address;
1123 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +01001124 top_address = caller_frame_top_ - output_frame_size;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001125 } else {
1126 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1127 }
1128 output_frame->SetTop(top_address);
1129
1130 // Compute the incoming parameter translation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001131 unsigned output_offset = output_frame_size;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001132 for (int i = 0; i < parameter_count; ++i) {
1133 output_offset -= kPointerSize;
1134 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1135 output_offset);
1136 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001137
1138 // There are no translation commands for the caller's pc and fp, the
1139 // context, the function, new.target and the bytecode offset. Synthesize
1140 // their values and set them up
1141 // explicitly.
1142 //
1143 // The caller's pc for the bottommost output frame is the same as in the
1144 // input frame. For all subsequent output frames, it can be read from the
1145 // previous one. This frame's pc can be computed from the non-optimized
1146 // function code and AST id of the bailout.
1147 output_offset -= kPCOnStackSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001148 intptr_t value;
1149 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +01001150 value = caller_pc_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001151 } else {
1152 value = output_[frame_index - 1]->GetPc();
1153 }
1154 output_frame->SetCallerPc(output_offset, value);
1155 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's pc\n");
1156
1157 // The caller's frame pointer for the bottommost output frame is the same
1158 // as in the input frame. For all subsequent output frames, it can be
1159 // read from the previous one. Also compute and set this frame's frame
1160 // pointer.
1161 output_offset -= kFPOnStackSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001162 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +01001163 value = caller_fp_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001164 } else {
1165 value = output_[frame_index - 1]->GetFp();
1166 }
1167 output_frame->SetCallerFp(output_offset, value);
1168 intptr_t fp_value = top_address + output_offset;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001169 output_frame->SetFp(fp_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001170 if (is_topmost) {
1171 Register fp_reg = InterpretedFrame::fp_register();
1172 output_frame->SetRegister(fp_reg.code(), fp_value);
1173 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001174 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001175
1176 if (FLAG_enable_embedded_constant_pool) {
1177 // For the bottommost output frame the constant pool pointer can be gotten
1178 // from the input frame. For subsequent output frames, it can be read from
1179 // the previous frame.
1180 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001181 if (is_bottommost) {
Ben Murdochda12d292016-06-02 14:46:10 +01001182 value = caller_constant_pool_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001183 } else {
1184 value = output_[frame_index - 1]->GetConstantPool();
1185 }
1186 output_frame->SetCallerConstantPool(output_offset, value);
1187 DebugPrintOutputSlot(value, frame_index, output_offset,
1188 "caller's constant_pool\n");
1189 }
1190
1191 // For the bottommost output frame the context can be gotten from the input
1192 // frame. For all subsequent output frames it can be gotten from the function
1193 // so long as we don't inline functions that need local contexts.
1194 Register context_reg = InterpretedFrame::context_register();
1195 output_offset -= kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001196
1197 // When deoptimizing into a catch block, we need to take the context
1198 // from a register that was specified in the handler table.
1199 TranslatedFrame::iterator context_pos = value_iterator;
1200 int context_input_index = input_index;
1201 if (goto_catch_handler) {
1202 // Skip to the translated value of the register specified
1203 // in the handler table.
1204 for (int i = 0; i < catch_handler_data_ + 1; ++i) {
1205 context_pos++;
1206 context_input_index++;
1207 }
1208 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001209 // Read the context from the translations.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001210 Object* context = context_pos->GetRawValue();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001211 // The context should not be a placeholder for a materialized object.
1212 CHECK(context != isolate_->heap()->arguments_marker());
1213 value = reinterpret_cast<intptr_t>(context);
1214 output_frame->SetContext(value);
1215 if (is_topmost) output_frame->SetRegister(context_reg.code(), value);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001216 WriteValueToOutput(context, context_input_index, frame_index, output_offset,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001217 "context ");
1218 value_iterator++;
1219 input_index++;
1220
1221 // The function was mentioned explicitly in the BEGIN_FRAME.
1222 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001223 value = reinterpret_cast<intptr_t>(function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001224 WriteValueToOutput(function, 0, frame_index, output_offset, "function ");
1225
Ben Murdoch097c5b22016-05-18 11:27:45 +01001226 // The new.target slot is only used during function activiation which is
1227 // before the first deopt point, so should never be needed. Just set it to
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001228 // undefined.
1229 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001230 Object* new_target = isolate_->heap()->undefined_value();
1231 WriteValueToOutput(new_target, 0, frame_index, output_offset, "new_target ");
1232
Ben Murdoch097c5b22016-05-18 11:27:45 +01001233 // Set the bytecode array pointer.
1234 output_offset -= kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001235 Object* bytecode_array = shared->bytecode_array();
1236 WriteValueToOutput(bytecode_array, 0, frame_index, output_offset,
1237 "bytecode array ");
1238
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001239 // The bytecode offset was mentioned explicitly in the BEGIN_FRAME.
1240 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001241 int raw_bytecode_offset =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001242 BytecodeArray::kHeaderSize - kHeapObjectTag + bytecode_offset;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001243 Smi* smi_bytecode_offset = Smi::FromInt(raw_bytecode_offset);
1244 WriteValueToOutput(smi_bytecode_offset, 0, frame_index, output_offset,
1245 "bytecode offset ");
1246
1247 // Translate the rest of the interpreter registers in the frame.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001248 for (unsigned i = 0; i < height - 1; ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001249 output_offset -= kPointerSize;
1250 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1251 output_offset);
1252 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001253
1254 // Put the accumulator on the stack. It will be popped by the
1255 // InterpreterNotifyDeopt builtin (possibly after materialization).
1256 output_offset -= kPointerSize;
1257 if (goto_catch_handler) {
1258 // If we are lazy deopting to a catch handler, we set the accumulator to
1259 // the exception (which lives in the result register).
1260 intptr_t accumulator_value =
1261 input_->GetRegister(FullCodeGenerator::result_register().code());
1262 WriteValueToOutput(reinterpret_cast<Object*>(accumulator_value), 0,
1263 frame_index, output_offset, "accumulator ");
1264 value_iterator++;
1265 } else {
1266 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1267 output_offset);
1268 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001269 CHECK_EQ(0u, output_offset);
1270
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001271 Builtins* builtins = isolate_->builtins();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001272 Code* dispatch_builtin =
1273 builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
1274 output_frame->SetPc(reinterpret_cast<intptr_t>(dispatch_builtin->entry()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001275 output_frame->SetState(0);
1276
1277 // Update constant pool.
1278 if (FLAG_enable_embedded_constant_pool) {
1279 intptr_t constant_pool_value =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001280 reinterpret_cast<intptr_t>(dispatch_builtin->constant_pool());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001281 output_frame->SetConstantPool(constant_pool_value);
1282 if (is_topmost) {
1283 Register constant_pool_reg =
1284 InterpretedFrame::constant_pool_pointer_register();
1285 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
1286 }
1287 }
1288
1289 // Set the continuation for the topmost frame.
Ben Murdochda12d292016-06-02 14:46:10 +01001290 if (is_topmost) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001291 Code* continuation =
1292 builtins->builtin(Builtins::kInterpreterNotifyDeoptimized);
1293 if (bailout_type_ == LAZY) {
1294 continuation =
1295 builtins->builtin(Builtins::kInterpreterNotifyLazyDeoptimized);
1296 } else if (bailout_type_ == SOFT) {
1297 continuation =
1298 builtins->builtin(Builtins::kInterpreterNotifySoftDeoptimized);
1299 } else {
1300 CHECK_EQ(bailout_type_, EAGER);
1301 }
1302 output_frame->SetContinuation(
1303 reinterpret_cast<intptr_t>(continuation->entry()));
1304 }
1305}
1306
Ben Murdochda12d292016-06-02 14:46:10 +01001307void Deoptimizer::DoComputeArgumentsAdaptorFrame(
1308 TranslatedFrame* translated_frame, int frame_index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001309 TranslatedFrame::iterator value_iterator = translated_frame->begin();
Ben Murdochda12d292016-06-02 14:46:10 +01001310 bool is_bottommost = (0 == frame_index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001311 int input_index = 0;
1312
1313 unsigned height = translated_frame->height();
1314 unsigned height_in_bytes = height * kPointerSize;
1315 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
1316 value_iterator++;
1317 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001318 if (trace_scope_ != NULL) {
1319 PrintF(trace_scope_->file(),
1320 " translating arguments adaptor => height=%d\n", height_in_bytes);
1321 }
1322
Ben Murdochda12d292016-06-02 14:46:10 +01001323 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFixedFrameSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001324 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1325
1326 // Allocate and store the output frame description.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001327 int parameter_count = height;
1328 FrameDescription* output_frame = new (output_frame_size)
1329 FrameDescription(output_frame_size, parameter_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001330 output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);
1331
Ben Murdochda12d292016-06-02 14:46:10 +01001332 // Arguments adaptor can not be topmost.
1333 CHECK(frame_index < output_count_ - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334 CHECK(output_[frame_index] == NULL);
1335 output_[frame_index] = output_frame;
1336
Ben Murdochda12d292016-06-02 14:46:10 +01001337 // The top address of the frame is computed from the previous frame's top and
1338 // this frame's size.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001339 intptr_t top_address;
Ben Murdochda12d292016-06-02 14:46:10 +01001340 if (is_bottommost) {
1341 top_address = caller_frame_top_ - output_frame_size;
1342 } else {
1343 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1344 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001345 output_frame->SetTop(top_address);
1346
1347 // Compute the incoming parameter translation.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001348 unsigned output_offset = output_frame_size;
1349 for (int i = 0; i < parameter_count; ++i) {
1350 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001351 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1352 output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001353 }
1354
1355 // Read caller's PC from the previous frame.
1356 output_offset -= kPCOnStackSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001357 intptr_t value;
1358 if (is_bottommost) {
1359 value = caller_pc_;
1360 } else {
1361 value = output_[frame_index - 1]->GetPc();
1362 }
1363 output_frame->SetCallerPc(output_offset, value);
1364 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001365
1366 // Read caller's FP from the previous frame, and set this frame's FP.
1367 output_offset -= kFPOnStackSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001368 if (is_bottommost) {
1369 value = caller_fp_;
1370 } else {
1371 value = output_[frame_index - 1]->GetFp();
1372 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001373 output_frame->SetCallerFp(output_offset, value);
1374 intptr_t fp_value = top_address + output_offset;
1375 output_frame->SetFp(fp_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001376 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001377
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001378 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001379 // Read the caller's constant pool from the previous frame.
1380 output_offset -= kPointerSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001381 if (is_bottommost) {
1382 value = caller_constant_pool_;
1383 } else {
1384 value = output_[frame_index - 1]->GetConstantPool();
1385 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001386 output_frame->SetCallerConstantPool(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001387 DebugPrintOutputSlot(value, frame_index, output_offset,
1388 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001389 }
1390
1391 // A marker value is used in place of the context.
1392 output_offset -= kPointerSize;
1393 intptr_t context = reinterpret_cast<intptr_t>(
1394 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1395 output_frame->SetFrameSlot(output_offset, context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001396 DebugPrintOutputSlot(context, frame_index, output_offset,
1397 "context (adaptor sentinel)\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001398
1399 // The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
1400 output_offset -= kPointerSize;
1401 value = reinterpret_cast<intptr_t>(function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001402 WriteValueToOutput(function, 0, frame_index, output_offset, "function ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001403
1404 // Number of incoming arguments.
1405 output_offset -= kPointerSize;
1406 value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
1407 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001408 DebugPrintOutputSlot(value, frame_index, output_offset, "argc ");
1409 if (trace_scope_ != nullptr) {
1410 PrintF(trace_scope_->file(), "(%d)\n", height - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001411 }
1412
1413 DCHECK(0 == output_offset);
1414
1415 Builtins* builtins = isolate_->builtins();
1416 Code* adaptor_trampoline =
1417 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
1418 intptr_t pc_value = reinterpret_cast<intptr_t>(
1419 adaptor_trampoline->instruction_start() +
1420 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
1421 output_frame->SetPc(pc_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001422 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001423 intptr_t constant_pool_value =
1424 reinterpret_cast<intptr_t>(adaptor_trampoline->constant_pool());
1425 output_frame->SetConstantPool(constant_pool_value);
1426 }
1427}
1428
Ben Murdochda12d292016-06-02 14:46:10 +01001429void Deoptimizer::DoComputeTailCallerFrame(TranslatedFrame* translated_frame,
1430 int frame_index) {
1431 SharedFunctionInfo* shared = translated_frame->raw_shared_info();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001432
Ben Murdochda12d292016-06-02 14:46:10 +01001433 bool is_bottommost = (0 == frame_index);
1434 // Tail caller frame can't be topmost.
1435 CHECK_NE(output_count_ - 1, frame_index);
1436
1437 if (trace_scope_ != NULL) {
1438 PrintF(trace_scope_->file(), " translating tail caller frame ");
1439 base::SmartArrayPointer<char> name = shared->DebugName()->ToCString();
1440 PrintF(trace_scope_->file(), "%s\n", name.get());
1441 }
1442
1443 if (!is_bottommost) return;
1444
1445 // Drop arguments adaptor frame below current frame if it exsits.
1446 Address fp_address = input_->GetFramePointerAddress();
1447 Address adaptor_fp_address =
1448 Memory::Address_at(fp_address + CommonFrameConstants::kCallerFPOffset);
1449
1450 if (Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR) !=
1451 Memory::Object_at(adaptor_fp_address +
1452 CommonFrameConstants::kContextOrFrameTypeOffset)) {
1453 return;
1454 }
1455
1456 int caller_params_count =
1457 Smi::cast(
1458 Memory::Object_at(adaptor_fp_address +
1459 ArgumentsAdaptorFrameConstants::kLengthOffset))
1460 ->value();
1461
1462 int callee_params_count =
1463 function_->shared()->internal_formal_parameter_count();
1464
1465 // Both caller and callee parameters count do not include receiver.
1466 int offset = (caller_params_count - callee_params_count) * kPointerSize;
1467 intptr_t new_stack_fp =
1468 reinterpret_cast<intptr_t>(adaptor_fp_address) + offset;
1469
1470 intptr_t new_caller_frame_top = new_stack_fp +
1471 (callee_params_count + 1) * kPointerSize +
1472 CommonFrameConstants::kFixedFrameSizeAboveFp;
1473
1474 intptr_t adaptor_caller_pc = Memory::intptr_at(
1475 adaptor_fp_address + CommonFrameConstants::kCallerPCOffset);
1476 intptr_t adaptor_caller_fp = Memory::intptr_at(
1477 adaptor_fp_address + CommonFrameConstants::kCallerFPOffset);
1478
1479 if (trace_scope_ != NULL) {
1480 PrintF(trace_scope_->file(),
1481 " dropping caller arguments adaptor frame: offset=%d, "
1482 "fp: 0x%08" V8PRIxPTR " -> 0x%08" V8PRIxPTR
1483 ", "
1484 "caller sp: 0x%08" V8PRIxPTR " -> 0x%08" V8PRIxPTR "\n",
1485 offset, stack_fp_, new_stack_fp, caller_frame_top_,
1486 new_caller_frame_top);
1487 }
1488 caller_frame_top_ = new_caller_frame_top;
1489 caller_fp_ = adaptor_caller_fp;
1490 caller_pc_ = adaptor_caller_pc;
1491}
1492
1493void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
1494 int frame_index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001495 TranslatedFrame::iterator value_iterator = translated_frame->begin();
Ben Murdochda12d292016-06-02 14:46:10 +01001496 bool is_topmost = (output_count_ - 1 == frame_index);
1497 // The construct frame could become topmost only if we inlined a constructor
1498 // call which does a tail call (otherwise the tail callee's frame would be
1499 // the topmost one). So it could only be the LAZY case.
1500 CHECK(!is_topmost || bailout_type_ == LAZY);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001501 int input_index = 0;
1502
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001503 Builtins* builtins = isolate_->builtins();
1504 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001505 unsigned height = translated_frame->height();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001506 unsigned height_in_bytes = height * kPointerSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001507
1508 // If the construct frame appears to be topmost we should ensure that the
1509 // value of result register is preserved during continuation execution.
1510 // We do this here by "pushing" the result of the constructor function to the
1511 // top of the reconstructed stack and then using the
1512 // FullCodeGenerator::TOS_REG machinery.
1513 if (is_topmost) {
1514 height_in_bytes += kPointerSize;
1515 }
1516
Ben Murdoch097c5b22016-05-18 11:27:45 +01001517 // Skip function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001518 value_iterator++;
1519 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001520 if (trace_scope_ != NULL) {
1521 PrintF(trace_scope_->file(),
1522 " translating construct stub => height=%d\n", height_in_bytes);
1523 }
1524
Ben Murdochda12d292016-06-02 14:46:10 +01001525 unsigned fixed_frame_size = ConstructFrameConstants::kFixedFrameSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001526 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1527
1528 // Allocate and store the output frame description.
1529 FrameDescription* output_frame =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001530 new (output_frame_size) FrameDescription(output_frame_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001531 output_frame->SetFrameType(StackFrame::CONSTRUCT);
1532
Ben Murdochda12d292016-06-02 14:46:10 +01001533 // Construct stub can not be topmost.
1534 DCHECK(frame_index > 0 && frame_index < output_count_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001535 DCHECK(output_[frame_index] == NULL);
1536 output_[frame_index] = output_frame;
1537
Ben Murdochda12d292016-06-02 14:46:10 +01001538 // The top address of the frame is computed from the previous frame's top and
1539 // this frame's size.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001540 intptr_t top_address;
1541 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1542 output_frame->SetTop(top_address);
1543
1544 // Compute the incoming parameter translation.
1545 int parameter_count = height;
1546 unsigned output_offset = output_frame_size;
1547 for (int i = 0; i < parameter_count; ++i) {
1548 output_offset -= kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001549 // The allocated receiver of a construct stub frame is passed as the
1550 // receiver parameter through the translation. It might be encoding
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001551 // a captured object, override the slot address for a captured object.
1552 WriteTranslatedValueToOutput(
1553 &value_iterator, &input_index, frame_index, output_offset, nullptr,
1554 (i == 0) ? reinterpret_cast<Address>(top_address) : nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001555 }
1556
1557 // Read caller's PC from the previous frame.
1558 output_offset -= kPCOnStackSize;
1559 intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1560 output_frame->SetCallerPc(output_offset, callers_pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001561 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001562
1563 // Read caller's FP from the previous frame, and set this frame's FP.
1564 output_offset -= kFPOnStackSize;
1565 intptr_t value = output_[frame_index - 1]->GetFp();
1566 output_frame->SetCallerFp(output_offset, value);
1567 intptr_t fp_value = top_address + output_offset;
1568 output_frame->SetFp(fp_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001569 if (is_topmost) {
1570 Register fp_reg = JavaScriptFrame::fp_register();
1571 output_frame->SetRegister(fp_reg.code(), fp_value);
1572 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001573 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001574
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001575 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001576 // Read the caller's constant pool from the previous frame.
1577 output_offset -= kPointerSize;
1578 value = output_[frame_index - 1]->GetConstantPool();
1579 output_frame->SetCallerConstantPool(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001580 DebugPrintOutputSlot(value, frame_index, output_offset,
1581 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001582 }
1583
Ben Murdochda12d292016-06-02 14:46:10 +01001584 // A marker value is used to mark the frame.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001585 output_offset -= kPointerSize;
1586 value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT));
1587 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001588 DebugPrintOutputSlot(value, frame_index, output_offset,
Ben Murdochda12d292016-06-02 14:46:10 +01001589 "typed frame marker\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001590
Ben Murdochda12d292016-06-02 14:46:10 +01001591 // The context can be gotten from the previous frame.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001592 output_offset -= kPointerSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001593 value = output_[frame_index - 1]->GetContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001594 output_frame->SetFrameSlot(output_offset, value);
Ben Murdochda12d292016-06-02 14:46:10 +01001595 if (is_topmost) {
1596 Register context_reg = JavaScriptFrame::context_register();
1597 output_frame->SetRegister(context_reg.code(), value);
1598 }
1599 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001600
1601 // The allocation site.
1602 output_offset -= kPointerSize;
1603 value = reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value());
1604 output_frame->SetFrameSlot(output_offset, value);
1605 DebugPrintOutputSlot(value, frame_index, output_offset, "allocation site\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001606
1607 // Number of incoming arguments.
1608 output_offset -= kPointerSize;
1609 value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
1610 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001611 DebugPrintOutputSlot(value, frame_index, output_offset, "argc ");
1612 if (trace_scope_ != nullptr) {
1613 PrintF(trace_scope_->file(), "(%d)\n", height - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001614 }
1615
1616 // The newly allocated object was passed as receiver in the artificial
1617 // constructor stub environment created by HEnvironment::CopyForInlining().
1618 output_offset -= kPointerSize;
1619 value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
1620 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001621 DebugPrintOutputSlot(value, frame_index, output_offset,
1622 "allocated receiver\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001623
Ben Murdochda12d292016-06-02 14:46:10 +01001624 if (is_topmost) {
1625 // Ensure the result is restored back when we return to the stub.
1626 output_offset -= kPointerSize;
1627 Register result_reg = FullCodeGenerator::result_register();
1628 value = input_->GetRegister(result_reg.code());
1629 output_frame->SetFrameSlot(output_offset, value);
1630 DebugPrintOutputSlot(value, frame_index, output_offset,
1631 "constructor result\n");
1632
1633 output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG));
1634 }
1635
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001636 CHECK_EQ(0u, output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001637
1638 intptr_t pc = reinterpret_cast<intptr_t>(
1639 construct_stub->instruction_start() +
1640 isolate_->heap()->construct_stub_deopt_pc_offset()->value());
1641 output_frame->SetPc(pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001642 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001643 intptr_t constant_pool_value =
1644 reinterpret_cast<intptr_t>(construct_stub->constant_pool());
1645 output_frame->SetConstantPool(constant_pool_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001646 if (is_topmost) {
1647 Register constant_pool_reg =
1648 JavaScriptFrame::constant_pool_pointer_register();
1649 output_frame->SetRegister(constant_pool_reg.code(), fp_value);
1650 }
1651 }
1652
1653 // Set the continuation for the topmost frame.
1654 if (is_topmost) {
1655 Builtins* builtins = isolate_->builtins();
1656 DCHECK_EQ(LAZY, bailout_type_);
1657 Code* continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
1658 output_frame->SetContinuation(
1659 reinterpret_cast<intptr_t>(continuation->entry()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001660 }
1661}
1662
Ben Murdochda12d292016-06-02 14:46:10 +01001663void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
1664 int frame_index,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001665 bool is_setter_stub_frame) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001666 TranslatedFrame::iterator value_iterator = translated_frame->begin();
Ben Murdochda12d292016-06-02 14:46:10 +01001667 bool is_topmost = (output_count_ - 1 == frame_index);
1668 // The accessor frame could become topmost only if we inlined an accessor
1669 // call which does a tail call (otherwise the tail callee's frame would be
1670 // the topmost one). So it could only be the LAZY case.
1671 CHECK(!is_topmost || bailout_type_ == LAZY);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001672 int input_index = 0;
1673
Ben Murdoch097c5b22016-05-18 11:27:45 +01001674 // Skip accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001675 value_iterator++;
1676 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001677 // The receiver (and the implicit return value, if any) are expected in
1678 // registers by the LoadIC/StoreIC, so they don't belong to the output stack
1679 // frame. This means that we have to use a height of 0.
1680 unsigned height = 0;
1681 unsigned height_in_bytes = height * kPointerSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001682
1683 // If the accessor frame appears to be topmost we should ensure that the
1684 // value of result register is preserved during continuation execution.
1685 // We do this here by "pushing" the result of the accessor function to the
1686 // top of the reconstructed stack and then using the
1687 // FullCodeGenerator::TOS_REG machinery.
1688 // We don't need to restore the result in case of a setter call because we
1689 // have to return the stored value but not the result of the setter function.
1690 bool should_preserve_result = is_topmost && !is_setter_stub_frame;
1691 if (should_preserve_result) {
1692 height_in_bytes += kPointerSize;
1693 }
1694
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001695 const char* kind = is_setter_stub_frame ? "setter" : "getter";
1696 if (trace_scope_ != NULL) {
1697 PrintF(trace_scope_->file(),
1698 " translating %s stub => height=%u\n", kind, height_in_bytes);
1699 }
1700
1701 // We need 1 stack entry for the return address and enough entries for the
Ben Murdochda12d292016-06-02 14:46:10 +01001702 // StackFrame::INTERNAL (FP, frame type, context, code object and constant
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001703 // pool (if enabled)- see MacroAssembler::EnterFrame).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001704 // For a setter stub frame we need one additional entry for the implicit
1705 // return value, see StoreStubCompiler::CompileStoreViaSetter.
1706 unsigned fixed_frame_entries =
1707 (StandardFrameConstants::kFixedFrameSize / kPointerSize) + 1 +
1708 (is_setter_stub_frame ? 1 : 0);
1709 unsigned fixed_frame_size = fixed_frame_entries * kPointerSize;
1710 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1711
1712 // Allocate and store the output frame description.
1713 FrameDescription* output_frame =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001714 new (output_frame_size) FrameDescription(output_frame_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001715 output_frame->SetFrameType(StackFrame::INTERNAL);
1716
Ben Murdochda12d292016-06-02 14:46:10 +01001717 // A frame for an accessor stub can not be bottommost.
1718 CHECK(frame_index > 0 && frame_index < output_count_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001719 CHECK_NULL(output_[frame_index]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001720 output_[frame_index] = output_frame;
1721
1722 // The top address of the frame is computed from the previous frame's top and
1723 // this frame's size.
1724 intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1725 output_frame->SetTop(top_address);
1726
1727 unsigned output_offset = output_frame_size;
1728
1729 // Read caller's PC from the previous frame.
1730 output_offset -= kPCOnStackSize;
1731 intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1732 output_frame->SetCallerPc(output_offset, callers_pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001733 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001734
1735 // Read caller's FP from the previous frame, and set this frame's FP.
1736 output_offset -= kFPOnStackSize;
1737 intptr_t value = output_[frame_index - 1]->GetFp();
1738 output_frame->SetCallerFp(output_offset, value);
1739 intptr_t fp_value = top_address + output_offset;
1740 output_frame->SetFp(fp_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001741 if (is_topmost) {
1742 Register fp_reg = JavaScriptFrame::fp_register();
1743 output_frame->SetRegister(fp_reg.code(), fp_value);
1744 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001745 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001746
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001747 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001748 // Read the caller's constant pool from the previous frame.
1749 output_offset -= kPointerSize;
1750 value = output_[frame_index - 1]->GetConstantPool();
1751 output_frame->SetCallerConstantPool(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001752 DebugPrintOutputSlot(value, frame_index, output_offset,
1753 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001754 }
1755
Ben Murdochda12d292016-06-02 14:46:10 +01001756 // Set the frame type.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001757 output_offset -= kPointerSize;
1758 value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::INTERNAL));
1759 output_frame->SetFrameSlot(output_offset, value);
Ben Murdochda12d292016-06-02 14:46:10 +01001760 DebugPrintOutputSlot(value, frame_index, output_offset, "frame type ");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001761 if (trace_scope_ != nullptr) {
1762 PrintF(trace_scope_->file(), "(%s sentinel)\n", kind);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001763 }
1764
1765 // Get Code object from accessor stub.
1766 output_offset -= kPointerSize;
1767 Builtins::Name name = is_setter_stub_frame ?
1768 Builtins::kStoreIC_Setter_ForDeopt :
1769 Builtins::kLoadIC_Getter_ForDeopt;
1770 Code* accessor_stub = isolate_->builtins()->builtin(name);
1771 value = reinterpret_cast<intptr_t>(accessor_stub);
1772 output_frame->SetFrameSlot(output_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001773 DebugPrintOutputSlot(value, frame_index, output_offset, "code object\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001774
Ben Murdochda12d292016-06-02 14:46:10 +01001775 // The context can be gotten from the previous frame.
1776 output_offset -= kPointerSize;
1777 value = output_[frame_index - 1]->GetContext();
1778 output_frame->SetFrameSlot(output_offset, value);
1779 if (is_topmost) {
1780 Register context_reg = JavaScriptFrame::context_register();
1781 output_frame->SetRegister(context_reg.code(), value);
1782 }
1783 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
1784
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001785 // Skip receiver.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001786 value_iterator++;
1787 input_index++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001788
1789 if (is_setter_stub_frame) {
1790 // The implicit return value was part of the artificial setter stub
1791 // environment.
1792 output_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001793 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
1794 output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001795 }
1796
Ben Murdochda12d292016-06-02 14:46:10 +01001797 if (should_preserve_result) {
1798 // Ensure the result is restored back when we return to the stub.
1799 output_offset -= kPointerSize;
1800 Register result_reg = FullCodeGenerator::result_register();
1801 value = input_->GetRegister(result_reg.code());
1802 output_frame->SetFrameSlot(output_offset, value);
1803 DebugPrintOutputSlot(value, frame_index, output_offset,
1804 "accessor result\n");
1805
1806 output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG));
1807 } else {
1808 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS));
1809 }
1810
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001811 CHECK_EQ(0u, output_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001812
1813 Smi* offset = is_setter_stub_frame ?
1814 isolate_->heap()->setter_stub_deopt_pc_offset() :
1815 isolate_->heap()->getter_stub_deopt_pc_offset();
1816 intptr_t pc = reinterpret_cast<intptr_t>(
1817 accessor_stub->instruction_start() + offset->value());
1818 output_frame->SetPc(pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001819 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001820 intptr_t constant_pool_value =
1821 reinterpret_cast<intptr_t>(accessor_stub->constant_pool());
1822 output_frame->SetConstantPool(constant_pool_value);
Ben Murdochda12d292016-06-02 14:46:10 +01001823 if (is_topmost) {
1824 Register constant_pool_reg =
1825 JavaScriptFrame::constant_pool_pointer_register();
1826 output_frame->SetRegister(constant_pool_reg.code(), fp_value);
1827 }
1828 }
1829
1830 // Set the continuation for the topmost frame.
1831 if (is_topmost) {
1832 Builtins* builtins = isolate_->builtins();
1833 DCHECK_EQ(LAZY, bailout_type_);
1834 Code* continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
1835 output_frame->SetContinuation(
1836 reinterpret_cast<intptr_t>(continuation->entry()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001837 }
1838}
1839
Ben Murdochda12d292016-06-02 14:46:10 +01001840void Deoptimizer::DoComputeCompiledStubFrame(TranslatedFrame* translated_frame,
1841 int frame_index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001842 //
1843 // FROM TO
1844 // | .... | | .... |
1845 // +-------------------------+ +-------------------------+
1846 // | JSFunction continuation | | JSFunction continuation |
1847 // +-------------------------+ +-------------------------+
1848 // | | saved frame (FP) | | saved frame (FP) |
1849 // | +=========================+<-fpreg +=========================+<-fpreg
1850 // | |constant pool (if ool_cp)| |constant pool (if ool_cp)|
1851 // | +-------------------------+ +-------------------------|
1852 // | | JSFunction context | | JSFunction context |
1853 // v +-------------------------+ +-------------------------|
1854 // | COMPILED_STUB marker | | STUB_FAILURE marker |
1855 // +-------------------------+ +-------------------------+
1856 // | | | caller args.arguments_ |
1857 // | ... | +-------------------------+
1858 // | | | caller args.length_ |
1859 // |-------------------------|<-spreg +-------------------------+
1860 // | caller args pointer |
1861 // +-------------------------+
1862 // | caller stack param 1 |
1863 // parameters in registers +-------------------------+
1864 // and spilled to stack | .... |
1865 // +-------------------------+
1866 // | caller stack param n |
1867 // +-------------------------+<-spreg
1868 // reg = number of parameters
1869 // reg = failure handler address
1870 // reg = saved frame
1871 // reg = JSFunction context
1872 //
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001873 // Caller stack params contain the register parameters to the stub first,
1874 // and then, if the descriptor specifies a constant number of stack
1875 // parameters, the stack parameters as well.
1876
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001877 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1878 int input_index = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001879
1880 CHECK(compiled_code_->is_hydrogen_stub());
1881 int major_key = CodeStub::GetMajorKey(compiled_code_);
1882 CodeStubDescriptor descriptor(isolate_, compiled_code_->stub_key());
1883
1884 // The output frame must have room for all pushed register parameters
1885 // and the standard stack frame slots. Include space for an argument
1886 // object to the callee and optionally the space to pass the argument
1887 // object to the stub failure handler.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001888 int param_count = descriptor.GetRegisterParameterCount();
1889 int stack_param_count = descriptor.GetStackParameterCount();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001890 // The translated frame contains all of the register parameters
1891 // plus the context.
1892 CHECK_EQ(translated_frame->height(), param_count + 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001893 CHECK_GE(param_count, 0);
1894
Ben Murdochda12d292016-06-02 14:46:10 +01001895 int height_in_bytes = kPointerSize * (param_count + stack_param_count);
1896 int fixed_frame_size = StubFailureTrampolineFrameConstants::kFixedFrameSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001897 int output_frame_size = height_in_bytes + fixed_frame_size;
1898 if (trace_scope_ != NULL) {
1899 PrintF(trace_scope_->file(),
1900 " translating %s => StubFailureTrampolineStub, height=%d\n",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001901 CodeStub::MajorName(static_cast<CodeStub::Major>(major_key)),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001902 height_in_bytes);
1903 }
1904
1905 // The stub failure trampoline is a single frame.
1906 FrameDescription* output_frame =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001907 new (output_frame_size) FrameDescription(output_frame_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001908 output_frame->SetFrameType(StackFrame::STUB_FAILURE_TRAMPOLINE);
1909 CHECK_EQ(frame_index, 0);
1910 output_[frame_index] = output_frame;
1911
Ben Murdochda12d292016-06-02 14:46:10 +01001912 // The top address of the frame is computed from the previous frame's top and
1913 // this frame's size.
1914 intptr_t top_address = caller_frame_top_ - output_frame_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001915 output_frame->SetTop(top_address);
1916
Ben Murdochda12d292016-06-02 14:46:10 +01001917 // Set caller's PC (JSFunction continuation).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001918 unsigned output_frame_offset = output_frame_size - kFPOnStackSize;
Ben Murdochda12d292016-06-02 14:46:10 +01001919 intptr_t value = caller_pc_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001920 output_frame->SetCallerPc(output_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001921 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
1922 "caller's pc\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001923
1924 // Read caller's FP from the input frame, and set this frame's FP.
Ben Murdochda12d292016-06-02 14:46:10 +01001925 value = caller_fp_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001926 output_frame_offset -= kFPOnStackSize;
1927 output_frame->SetCallerFp(output_frame_offset, value);
Ben Murdochda12d292016-06-02 14:46:10 +01001928 intptr_t frame_ptr = top_address + output_frame_offset;
1929 Register fp_reg = StubFailureTrampolineFrame::fp_register();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001930 output_frame->SetRegister(fp_reg.code(), frame_ptr);
1931 output_frame->SetFp(frame_ptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001932 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
1933 "caller's fp\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001934
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001935 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001936 // Read the caller's constant pool from the input frame.
Ben Murdochda12d292016-06-02 14:46:10 +01001937 value = caller_constant_pool_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001938 output_frame_offset -= kPointerSize;
1939 output_frame->SetCallerConstantPool(output_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001940 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
1941 "caller's constant_pool\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001942 }
1943
Ben Murdochda12d292016-06-02 14:46:10 +01001944 // The marker for the typed stack frame
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001945 output_frame_offset -= kPointerSize;
1946 value = reinterpret_cast<intptr_t>(
1947 Smi::FromInt(StackFrame::STUB_FAILURE_TRAMPOLINE));
1948 output_frame->SetFrameSlot(output_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001949 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
1950 "function (stub failure sentinel)\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001951
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001952 intptr_t caller_arg_count = stack_param_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001953 bool arg_count_known = !descriptor.stack_parameter_count().is_valid();
1954
1955 // Build the Arguments object for the caller's parameters and a pointer to it.
1956 output_frame_offset -= kPointerSize;
1957 int args_arguments_offset = output_frame_offset;
1958 intptr_t the_hole = reinterpret_cast<intptr_t>(
1959 isolate_->heap()->the_hole_value());
1960 if (arg_count_known) {
1961 value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
1962 (caller_arg_count - 1) * kPointerSize;
1963 } else {
1964 value = the_hole;
1965 }
1966
1967 output_frame->SetFrameSlot(args_arguments_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001968 DebugPrintOutputSlot(
1969 value, frame_index, args_arguments_offset,
1970 arg_count_known ? "args.arguments\n" : "args.arguments (the hole)\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001971
1972 output_frame_offset -= kPointerSize;
1973 int length_frame_offset = output_frame_offset;
1974 value = arg_count_known ? caller_arg_count : the_hole;
1975 output_frame->SetFrameSlot(length_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001976 DebugPrintOutputSlot(
1977 value, frame_index, length_frame_offset,
1978 arg_count_known ? "args.length\n" : "args.length (the hole)\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001979
1980 output_frame_offset -= kPointerSize;
1981 value = frame_ptr + StandardFrameConstants::kCallerSPOffset -
1982 (output_frame_size - output_frame_offset) + kPointerSize;
1983 output_frame->SetFrameSlot(output_frame_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001984 DebugPrintOutputSlot(value, frame_index, output_frame_offset, "args*\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001985
1986 // Copy the register parameters to the failure frame.
1987 int arguments_length_offset = -1;
1988 for (int i = 0; i < param_count; ++i) {
1989 output_frame_offset -= kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001990 WriteTranslatedValueToOutput(&value_iterator, &input_index, 0,
1991 output_frame_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001992
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001993 if (!arg_count_known &&
1994 descriptor.GetRegisterParameter(i)
1995 .is(descriptor.stack_parameter_count())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001996 arguments_length_offset = output_frame_offset;
1997 }
1998 }
1999
Ben Murdoch097c5b22016-05-18 11:27:45 +01002000 Object* maybe_context = value_iterator->GetRawValue();
2001 CHECK(maybe_context->IsContext());
2002 Register context_reg = StubFailureTrampolineFrame::context_register();
2003 value = reinterpret_cast<intptr_t>(maybe_context);
2004 output_frame->SetRegister(context_reg.code(), value);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002005 ++value_iterator;
2006
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002007 // Copy constant stack parameters to the failure frame. If the number of stack
2008 // parameters is not known in the descriptor, the arguments object is the way
2009 // to access them.
2010 for (int i = 0; i < stack_param_count; i++) {
2011 output_frame_offset -= kPointerSize;
2012 Object** stack_parameter = reinterpret_cast<Object**>(
2013 frame_ptr + StandardFrameConstants::kCallerSPOffset +
2014 (stack_param_count - i - 1) * kPointerSize);
2015 value = reinterpret_cast<intptr_t>(*stack_parameter);
2016 output_frame->SetFrameSlot(output_frame_offset, value);
2017 DebugPrintOutputSlot(value, frame_index, output_frame_offset,
2018 "stack parameter\n");
2019 }
2020
2021 CHECK_EQ(0u, output_frame_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002022
2023 if (!arg_count_known) {
2024 CHECK_GE(arguments_length_offset, 0);
2025 // We know it's a smi because 1) the code stub guarantees the stack
2026 // parameter count is in smi range, and 2) the DoTranslateCommand in the
2027 // parameter loop above translated that to a tagged value.
2028 Smi* smi_caller_arg_count = reinterpret_cast<Smi*>(
2029 output_frame->GetFrameSlot(arguments_length_offset));
2030 caller_arg_count = smi_caller_arg_count->value();
2031 output_frame->SetFrameSlot(length_frame_offset, caller_arg_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002032 DebugPrintOutputSlot(caller_arg_count, frame_index, length_frame_offset,
2033 "args.length\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002034 value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
2035 (caller_arg_count - 1) * kPointerSize;
2036 output_frame->SetFrameSlot(args_arguments_offset, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002037 DebugPrintOutputSlot(value, frame_index, args_arguments_offset,
2038 "args.arguments");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002039 }
2040
2041 // Copy the double registers from the input into the output frame.
2042 CopyDoubleRegisters(output_frame);
2043
2044 // Fill registers containing handler and number of parameters.
2045 SetPlatformCompiledStubRegisters(output_frame, &descriptor);
2046
2047 // Compute this frame's PC, state, and continuation.
2048 Code* trampoline = NULL;
2049 StubFunctionMode function_mode = descriptor.function_mode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002050 StubFailureTrampolineStub(isolate_, function_mode)
2051 .FindCodeInCache(&trampoline);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002052 DCHECK(trampoline != NULL);
2053 output_frame->SetPc(reinterpret_cast<intptr_t>(
2054 trampoline->instruction_start()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002055 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002056 Register constant_pool_reg =
2057 StubFailureTrampolineFrame::constant_pool_pointer_register();
2058 intptr_t constant_pool_value =
2059 reinterpret_cast<intptr_t>(trampoline->constant_pool());
2060 output_frame->SetConstantPool(constant_pool_value);
2061 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
2062 }
2063 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS));
2064 Code* notify_failure =
2065 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles);
2066 output_frame->SetContinuation(
2067 reinterpret_cast<intptr_t>(notify_failure->entry()));
2068}
2069
2070
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002071void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002072 // Walk to the last JavaScript output frame to find out if it has
2073 // adapted arguments.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002074 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
2075 if (frame_index != 0) it->Advance();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002076 }
Ben Murdochda12d292016-06-02 14:46:10 +01002077 translated_state_.Prepare(it->frame()->has_adapted_arguments(),
2078 reinterpret_cast<Address>(stack_fp_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002079
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002080 for (auto& materialization : values_to_materialize_) {
2081 Handle<Object> value = materialization.value_->GetValue();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002082
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002083 if (trace_scope_ != nullptr) {
2084 PrintF("Materialization [0x%08" V8PRIxPTR "] <- 0x%08" V8PRIxPTR " ; ",
2085 reinterpret_cast<intptr_t>(materialization.output_slot_address_),
2086 reinterpret_cast<intptr_t>(*value));
2087 value->ShortPrint(trace_scope_->file());
2088 PrintF(trace_scope_->file(), "\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002089 }
2090
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002091 *(reinterpret_cast<intptr_t*>(materialization.output_slot_address_)) =
2092 reinterpret_cast<intptr_t>(*value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002093 }
2094
Ben Murdochda12d292016-06-02 14:46:10 +01002095 isolate_->materialized_object_store()->Remove(
2096 reinterpret_cast<Address>(stack_fp_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002097}
2098
2099
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002100void Deoptimizer::WriteTranslatedValueToOutput(
2101 TranslatedFrame::iterator* iterator, int* input_index, int frame_index,
2102 unsigned output_offset, const char* debug_hint_string,
2103 Address output_address_for_materialization) {
2104 Object* value = (*iterator)->GetRawValue();
2105
2106 WriteValueToOutput(value, *input_index, frame_index, output_offset,
2107 debug_hint_string);
2108
2109 if (value == isolate_->heap()->arguments_marker()) {
2110 Address output_address =
2111 reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
2112 output_offset;
2113 if (output_address_for_materialization == nullptr) {
2114 output_address_for_materialization = output_address;
2115 }
2116 values_to_materialize_.push_back(
2117 {output_address_for_materialization, *iterator});
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002118 }
2119
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002120 (*iterator)++;
2121 (*input_index)++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002122}
2123
2124
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002125void Deoptimizer::WriteValueToOutput(Object* value, int input_index,
2126 int frame_index, unsigned output_offset,
2127 const char* debug_hint_string) {
2128 output_[frame_index]->SetFrameSlot(output_offset,
2129 reinterpret_cast<intptr_t>(value));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002130
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002131 if (trace_scope_ != nullptr) {
2132 DebugPrintOutputSlot(reinterpret_cast<intptr_t>(value), frame_index,
2133 output_offset, debug_hint_string);
2134 value->ShortPrint(trace_scope_->file());
2135 PrintF(trace_scope_->file(), " (input #%d)\n", input_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002136 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002137}
2138
2139
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002140void Deoptimizer::DebugPrintOutputSlot(intptr_t value, int frame_index,
2141 unsigned output_offset,
2142 const char* debug_hint_string) {
2143 if (trace_scope_ != nullptr) {
2144 Address output_address =
2145 reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
2146 output_offset;
2147 PrintF(trace_scope_->file(),
2148 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s",
2149 reinterpret_cast<intptr_t>(output_address), output_offset, value,
2150 debug_hint_string == nullptr ? "" : debug_hint_string);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002151 }
2152}
2153
Ben Murdochda12d292016-06-02 14:46:10 +01002154unsigned Deoptimizer::ComputeInputFrameAboveFpFixedSize() const {
2155 unsigned fixed_size = CommonFrameConstants::kFixedFrameSizeAboveFp;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002156 if (!function_->IsSmi()) {
2157 fixed_size += ComputeIncomingArgumentSize(function_->shared());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002158 }
Ben Murdochda12d292016-06-02 14:46:10 +01002159 return fixed_size;
2160}
2161
2162unsigned Deoptimizer::ComputeInputFrameSize() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002163 // The fp-to-sp delta already takes the context, constant pool pointer and the
2164 // function into account so we have to avoid double counting them.
Ben Murdochda12d292016-06-02 14:46:10 +01002165 unsigned fixed_size_above_fp = ComputeInputFrameAboveFpFixedSize();
2166 unsigned result = fixed_size_above_fp + fp_to_sp_delta_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002167 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
2168 unsigned stack_slots = compiled_code_->stack_slots();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002169 unsigned outgoing_size =
2170 ComputeOutgoingArgumentSize(compiled_code_, bailout_id_);
Ben Murdochda12d292016-06-02 14:46:10 +01002171 CHECK_EQ(fixed_size_above_fp + (stack_slots * kPointerSize) -
2172 CommonFrameConstants::kFixedFrameSizeAboveFp + outgoing_size,
2173 result);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002174 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01002175 return result;
2176}
2177
Ben Murdoch097c5b22016-05-18 11:27:45 +01002178// static
2179unsigned Deoptimizer::ComputeJavascriptFixedSize(SharedFunctionInfo* shared) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002180 // The fixed part of the frame consists of the return address, frame
2181 // pointer, function, context, and all the incoming arguments.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002182 return ComputeIncomingArgumentSize(shared) +
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002183 StandardFrameConstants::kFixedFrameSize;
2184}
2185
Ben Murdoch097c5b22016-05-18 11:27:45 +01002186// static
2187unsigned Deoptimizer::ComputeInterpretedFixedSize(SharedFunctionInfo* shared) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002188 // The fixed part of the frame consists of the return address, frame
2189 // pointer, function, context, new.target, bytecode offset and all the
2190 // incoming arguments.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002191 return ComputeIncomingArgumentSize(shared) +
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002192 InterpreterFrameConstants::kFixedFrameSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002193}
2194
Ben Murdoch097c5b22016-05-18 11:27:45 +01002195// static
2196unsigned Deoptimizer::ComputeIncomingArgumentSize(SharedFunctionInfo* shared) {
2197 return (shared->internal_formal_parameter_count() + 1) * kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002198}
2199
2200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002201// static
2202unsigned Deoptimizer::ComputeOutgoingArgumentSize(Code* code,
2203 unsigned bailout_id) {
2204 DeoptimizationInputData* data =
2205 DeoptimizationInputData::cast(code->deoptimization_data());
2206 unsigned height = data->ArgumentsStackHeight(bailout_id)->value();
Ben Murdochb0fe1622011-05-05 13:52:32 +01002207 return height * kPointerSize;
2208}
2209
2210
2211Object* Deoptimizer::ComputeLiteral(int index) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002212 DeoptimizationInputData* data =
2213 DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002214 FixedArray* literals = data->LiteralArray();
2215 return literals->get(index);
2216}
2217
2218
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002219void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate,
2220 BailoutType type,
2221 int max_entry_id) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002222 // We cannot run this if the serializer is enabled because this will
2223 // cause us to emit relocation information for the external
2224 // references. This is fine because the deoptimizer's code section
2225 // isn't meant to be serialized at all.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002226 CHECK(type == EAGER || type == SOFT || type == LAZY);
2227 DeoptimizerData* data = isolate->deoptimizer_data();
2228 int entry_count = data->deopt_entry_code_entries_[type];
2229 if (max_entry_id < entry_count) return;
2230 entry_count = Max(entry_count, Deoptimizer::kMinNumberOfEntries);
2231 while (max_entry_id >= entry_count) entry_count *= 2;
2232 CHECK(entry_count <= Deoptimizer::kMaxNumberOfEntries);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002233
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002234 MacroAssembler masm(isolate, NULL, 16 * KB, CodeObjectRequired::kYes);
Steve Block44f0eee2011-05-26 01:26:41 +01002235 masm.set_emit_debug_code(false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002236 GenerateDeoptimizationEntries(&masm, entry_count, type);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002237 CodeDesc desc;
2238 masm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002239 DCHECK(!RelocInfo::RequiresRelocation(desc));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002240
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002241 MemoryChunk* chunk = data->deopt_entry_code_[type];
2242 CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >=
2243 desc.instr_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002244 if (!chunk->CommitArea(desc.instr_size)) {
2245 V8::FatalProcessOutOfMemory(
2246 "Deoptimizer::EnsureCodeForDeoptimizationEntry");
2247 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002248 CopyBytes(chunk->area_start(), desc.buffer,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002249 static_cast<size_t>(desc.instr_size));
2250 Assembler::FlushICache(isolate, chunk->area_start(), desc.instr_size);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002251
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002252 data->deopt_entry_code_entries_[type] = entry_count;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002253}
2254
Ben Murdoch097c5b22016-05-18 11:27:45 +01002255FrameDescription::FrameDescription(uint32_t frame_size, int parameter_count)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002256 : frame_size_(frame_size),
Ben Murdoch097c5b22016-05-18 11:27:45 +01002257 parameter_count_(parameter_count),
Ben Murdochb0fe1622011-05-05 13:52:32 +01002258 top_(kZapUint32),
2259 pc_(kZapUint32),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002260 fp_(kZapUint32),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002261 context_(kZapUint32),
2262 constant_pool_(kZapUint32) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002263 // Zap all the registers.
2264 for (int r = 0; r < Register::kNumRegisters; r++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002265 // TODO(jbramley): It isn't safe to use kZapUint32 here. If the register
2266 // isn't used before the next safepoint, the GC will try to scan it as a
2267 // tagged value. kZapUint32 looks like a valid tagged pointer, but it isn't.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002268 SetRegister(r, kZapUint32);
2269 }
2270
2271 // Zap all the slots.
2272 for (unsigned o = 0; o < frame_size; o += kPointerSize) {
2273 SetFrameSlot(o, kZapUint32);
2274 }
2275}
2276
2277
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002278int FrameDescription::ComputeFixedSize() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002279 if (type_ == StackFrame::INTERPRETED) {
2280 return InterpreterFrameConstants::kFixedFrameSize +
Ben Murdoch097c5b22016-05-18 11:27:45 +01002281 parameter_count() * kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002282 } else {
2283 return StandardFrameConstants::kFixedFrameSize +
Ben Murdoch097c5b22016-05-18 11:27:45 +01002284 parameter_count() * kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002285 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002286}
2287
2288
2289unsigned FrameDescription::GetOffsetFromSlotIndex(int slot_index) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002290 if (slot_index >= 0) {
2291 // Local or spill slots. Skip the fixed part of the frame
2292 // including all arguments.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002293 unsigned base = GetFrameSize() - ComputeFixedSize();
Ben Murdochb0fe1622011-05-05 13:52:32 +01002294 return base - ((slot_index + 1) * kPointerSize);
2295 } else {
2296 // Incoming parameter.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002297 int arg_size = parameter_count() * kPointerSize;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002298 unsigned base = GetFrameSize() - arg_size;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002299 return base - ((slot_index + 1) * kPointerSize);
2300 }
2301}
2302
2303
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002304void TranslationBuffer::Add(int32_t value, Zone* zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002305 // This wouldn't handle kMinInt correctly if it ever encountered it.
2306 DCHECK(value != kMinInt);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002307 // Encode the sign bit in the least significant bit.
2308 bool is_negative = (value < 0);
2309 uint32_t bits = ((is_negative ? -value : value) << 1) |
2310 static_cast<int32_t>(is_negative);
2311 // Encode the individual bytes using the least significant bit of
2312 // each byte to indicate whether or not more bytes follow.
2313 do {
2314 uint32_t next = bits >> 7;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002315 contents_.Add(((bits << 1) & 0xFF) | (next != 0), zone);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002316 bits = next;
2317 } while (bits != 0);
2318}
2319
2320
2321int32_t TranslationIterator::Next() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002322 // Run through the bytes until we reach one with a least significant
2323 // bit of zero (marks the end).
2324 uint32_t bits = 0;
2325 for (int i = 0; true; i += 7) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002326 DCHECK(HasNext());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002327 uint8_t next = buffer_->get(index_++);
2328 bits |= (next >> 1) << i;
2329 if ((next & 1) == 0) break;
2330 }
2331 // The bits encode the sign in the least significant bit.
2332 bool is_negative = (bits & 1) == 1;
2333 int32_t result = bits >> 1;
2334 return is_negative ? -result : result;
2335}
2336
2337
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002338Handle<ByteArray> TranslationBuffer::CreateByteArray(Factory* factory) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002339 int length = contents_.length();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002340 Handle<ByteArray> result = factory->NewByteArray(length, TENURED);
2341 MemCopy(result->GetDataStartAddress(), contents_.ToVector().start(), length);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002342 return result;
2343}
2344
2345
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002346void Translation::BeginConstructStubFrame(int literal_id, unsigned height) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002347 buffer_->Add(CONSTRUCT_STUB_FRAME, zone());
2348 buffer_->Add(literal_id, zone());
2349 buffer_->Add(height, zone());
2350}
2351
2352
2353void Translation::BeginGetterStubFrame(int literal_id) {
2354 buffer_->Add(GETTER_STUB_FRAME, zone());
2355 buffer_->Add(literal_id, zone());
2356}
2357
2358
2359void Translation::BeginSetterStubFrame(int literal_id) {
2360 buffer_->Add(SETTER_STUB_FRAME, zone());
2361 buffer_->Add(literal_id, zone());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002362}
2363
2364
2365void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002366 buffer_->Add(ARGUMENTS_ADAPTOR_FRAME, zone());
2367 buffer_->Add(literal_id, zone());
2368 buffer_->Add(height, zone());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002369}
2370
Ben Murdochda12d292016-06-02 14:46:10 +01002371void Translation::BeginTailCallerFrame(int literal_id) {
2372 buffer_->Add(TAIL_CALLER_FRAME, zone());
2373 buffer_->Add(literal_id, zone());
2374}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002375
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002376void Translation::BeginJSFrame(BailoutId node_id,
2377 int literal_id,
2378 unsigned height) {
2379 buffer_->Add(JS_FRAME, zone());
2380 buffer_->Add(node_id.ToInt(), zone());
2381 buffer_->Add(literal_id, zone());
2382 buffer_->Add(height, zone());
2383}
2384
2385
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002386void Translation::BeginInterpretedFrame(BailoutId bytecode_offset,
2387 int literal_id, unsigned height) {
2388 buffer_->Add(INTERPRETED_FRAME, zone());
2389 buffer_->Add(bytecode_offset.ToInt(), zone());
2390 buffer_->Add(literal_id, zone());
2391 buffer_->Add(height, zone());
2392}
2393
2394
2395void Translation::BeginCompiledStubFrame(int height) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002396 buffer_->Add(COMPILED_STUB_FRAME, zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002397 buffer_->Add(height, zone());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002398}
2399
2400
2401void Translation::BeginArgumentsObject(int args_length) {
2402 buffer_->Add(ARGUMENTS_OBJECT, zone());
2403 buffer_->Add(args_length, zone());
2404}
2405
2406
2407void Translation::BeginCapturedObject(int length) {
2408 buffer_->Add(CAPTURED_OBJECT, zone());
2409 buffer_->Add(length, zone());
2410}
2411
2412
2413void Translation::DuplicateObject(int object_index) {
2414 buffer_->Add(DUPLICATED_OBJECT, zone());
2415 buffer_->Add(object_index, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002416}
2417
2418
2419void Translation::StoreRegister(Register reg) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002420 buffer_->Add(REGISTER, zone());
2421 buffer_->Add(reg.code(), zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002422}
2423
2424
2425void Translation::StoreInt32Register(Register reg) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002426 buffer_->Add(INT32_REGISTER, zone());
2427 buffer_->Add(reg.code(), zone());
2428}
2429
2430
2431void Translation::StoreUint32Register(Register reg) {
2432 buffer_->Add(UINT32_REGISTER, zone());
2433 buffer_->Add(reg.code(), zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002434}
2435
2436
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002437void Translation::StoreBoolRegister(Register reg) {
2438 buffer_->Add(BOOL_REGISTER, zone());
2439 buffer_->Add(reg.code(), zone());
2440}
2441
2442
Ben Murdochb0fe1622011-05-05 13:52:32 +01002443void Translation::StoreDoubleRegister(DoubleRegister reg) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002444 buffer_->Add(DOUBLE_REGISTER, zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002445 buffer_->Add(reg.code(), zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002446}
2447
2448
2449void Translation::StoreStackSlot(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002450 buffer_->Add(STACK_SLOT, zone());
2451 buffer_->Add(index, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002452}
2453
2454
2455void Translation::StoreInt32StackSlot(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002456 buffer_->Add(INT32_STACK_SLOT, zone());
2457 buffer_->Add(index, zone());
2458}
2459
2460
2461void Translation::StoreUint32StackSlot(int index) {
2462 buffer_->Add(UINT32_STACK_SLOT, zone());
2463 buffer_->Add(index, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002464}
2465
2466
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002467void Translation::StoreBoolStackSlot(int index) {
2468 buffer_->Add(BOOL_STACK_SLOT, zone());
2469 buffer_->Add(index, zone());
2470}
2471
2472
Ben Murdochb0fe1622011-05-05 13:52:32 +01002473void Translation::StoreDoubleStackSlot(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002474 buffer_->Add(DOUBLE_STACK_SLOT, zone());
2475 buffer_->Add(index, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002476}
2477
2478
2479void Translation::StoreLiteral(int literal_id) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002480 buffer_->Add(LITERAL, zone());
2481 buffer_->Add(literal_id, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002482}
2483
2484
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002485void Translation::StoreArgumentsObject(bool args_known,
2486 int args_index,
2487 int args_length) {
2488 buffer_->Add(ARGUMENTS_OBJECT, zone());
2489 buffer_->Add(args_known, zone());
2490 buffer_->Add(args_index, zone());
2491 buffer_->Add(args_length, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002492}
2493
2494
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002495void Translation::StoreJSFrameFunction() {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002496 StoreStackSlot((StandardFrameConstants::kCallerPCOffset -
Ben Murdochda12d292016-06-02 14:46:10 +01002497 StandardFrameConstants::kFunctionOffset) /
Ben Murdoch097c5b22016-05-18 11:27:45 +01002498 kPointerSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002499}
2500
Ben Murdochb0fe1622011-05-05 13:52:32 +01002501int Translation::NumberOfOperandsFor(Opcode opcode) {
2502 switch (opcode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002503 case GETTER_STUB_FRAME:
2504 case SETTER_STUB_FRAME:
2505 case DUPLICATED_OBJECT:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002506 case ARGUMENTS_OBJECT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002507 case CAPTURED_OBJECT:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002508 case REGISTER:
2509 case INT32_REGISTER:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002510 case UINT32_REGISTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002511 case BOOL_REGISTER:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002512 case DOUBLE_REGISTER:
2513 case STACK_SLOT:
2514 case INT32_STACK_SLOT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002515 case UINT32_STACK_SLOT:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002516 case BOOL_STACK_SLOT:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002517 case DOUBLE_STACK_SLOT:
2518 case LITERAL:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002519 case COMPILED_STUB_FRAME:
Ben Murdochda12d292016-06-02 14:46:10 +01002520 case TAIL_CALLER_FRAME:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002521 return 1;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002522 case BEGIN:
2523 case ARGUMENTS_ADAPTOR_FRAME:
2524 case CONSTRUCT_STUB_FRAME:
2525 return 2;
2526 case JS_FRAME:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002527 case INTERPRETED_FRAME:
Ben Murdochb0fe1622011-05-05 13:52:32 +01002528 return 3;
2529 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002530 FATAL("Unexpected translation type");
Ben Murdochb0fe1622011-05-05 13:52:32 +01002531 return -1;
2532}
2533
2534
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002535#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002536
2537const char* Translation::StringFor(Opcode opcode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002538#define TRANSLATION_OPCODE_CASE(item) case item: return #item;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002539 switch (opcode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002540 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002541 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002542#undef TRANSLATION_OPCODE_CASE
Ben Murdochb0fe1622011-05-05 13:52:32 +01002543 UNREACHABLE();
2544 return "";
2545}
2546
2547#endif
2548
2549
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002550Handle<FixedArray> MaterializedObjectStore::Get(Address fp) {
2551 int index = StackIdToIndex(fp);
2552 if (index == -1) {
2553 return Handle<FixedArray>::null();
2554 }
2555 Handle<FixedArray> array = GetStackEntries();
2556 CHECK_GT(array->length(), index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002557 return Handle<FixedArray>::cast(Handle<Object>(array->get(index), isolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002558}
2559
2560
2561void MaterializedObjectStore::Set(Address fp,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002562 Handle<FixedArray> materialized_objects) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002563 int index = StackIdToIndex(fp);
2564 if (index == -1) {
2565 index = frame_fps_.length();
2566 frame_fps_.Add(fp);
2567 }
2568
2569 Handle<FixedArray> array = EnsureStackEntries(index + 1);
2570 array->set(index, *materialized_objects);
2571}
2572
2573
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002574bool MaterializedObjectStore::Remove(Address fp) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002575 int index = StackIdToIndex(fp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002576 if (index == -1) {
2577 return false;
2578 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002579 CHECK_GE(index, 0);
2580
2581 frame_fps_.Remove(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002582 FixedArray* array = isolate()->heap()->materialized_objects();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002583 CHECK_LT(index, array->length());
2584 for (int i = index; i < frame_fps_.length(); i++) {
2585 array->set(i, array->get(i + 1));
2586 }
2587 array->set(frame_fps_.length(), isolate()->heap()->undefined_value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002588 return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002589}
2590
2591
2592int MaterializedObjectStore::StackIdToIndex(Address fp) {
2593 for (int i = 0; i < frame_fps_.length(); i++) {
2594 if (frame_fps_[i] == fp) {
2595 return i;
2596 }
2597 }
2598 return -1;
2599}
2600
2601
2602Handle<FixedArray> MaterializedObjectStore::GetStackEntries() {
2603 return Handle<FixedArray>(isolate()->heap()->materialized_objects());
2604}
2605
2606
2607Handle<FixedArray> MaterializedObjectStore::EnsureStackEntries(int length) {
2608 Handle<FixedArray> array = GetStackEntries();
2609 if (array->length() >= length) {
2610 return array;
2611 }
2612
2613 int new_length = length > 10 ? length : 10;
2614 if (new_length < 2 * array->length()) {
2615 new_length = 2 * array->length();
2616 }
2617
2618 Handle<FixedArray> new_array =
2619 isolate()->factory()->NewFixedArray(new_length, TENURED);
2620 for (int i = 0; i < array->length(); i++) {
2621 new_array->set(i, array->get(i));
2622 }
2623 for (int i = array->length(); i < length; i++) {
2624 new_array->set(i, isolate()->heap()->undefined_value());
2625 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002626 isolate()->heap()->SetRootMaterializedObjects(*new_array);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002627 return new_array;
2628}
2629
Ben Murdoch097c5b22016-05-18 11:27:45 +01002630namespace {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002631
Ben Murdoch097c5b22016-05-18 11:27:45 +01002632Handle<Object> GetValueForDebugger(TranslatedFrame::iterator it,
2633 Isolate* isolate) {
2634 if (it->GetRawValue() == isolate->heap()->arguments_marker()) {
2635 if (!it->IsMaterializableByDebugger()) {
2636 return isolate->factory()->undefined_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002637 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002638 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002639 return it->GetValue();
2640}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002641
Ben Murdoch097c5b22016-05-18 11:27:45 +01002642int ComputeSourcePosition(Handle<SharedFunctionInfo> shared,
2643 BailoutId node_id) {
2644 if (shared->HasBytecodeArray()) {
2645 BytecodeArray* bytecodes = shared->bytecode_array();
Ben Murdochda12d292016-06-02 14:46:10 +01002646 // BailoutId points to the next bytecode in the bytecode aray. Subtract
2647 // 1 to get the end of current bytecode.
2648 return bytecodes->SourcePosition(node_id.ToInt() - 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002649 } else {
2650 Code* non_optimized_code = shared->code();
2651 FixedArray* raw_data = non_optimized_code->deoptimization_data();
2652 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
2653 unsigned pc_and_state = Deoptimizer::GetOutputInfo(data, node_id, *shared);
2654 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
2655 return non_optimized_code->SourcePosition(pc_offset);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002656 }
2657}
2658
Ben Murdoch097c5b22016-05-18 11:27:45 +01002659} // namespace
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002660
Ben Murdoch097c5b22016-05-18 11:27:45 +01002661DeoptimizedFrameInfo::DeoptimizedFrameInfo(TranslatedState* state,
2662 TranslatedState::iterator frame_it,
2663 Isolate* isolate) {
2664 // If the previous frame is an adaptor frame, we will take the parameters
2665 // from there.
2666 TranslatedState::iterator parameter_frame = frame_it;
2667 if (parameter_frame != state->begin()) {
2668 parameter_frame--;
2669 }
2670 int parameter_count;
2671 if (parameter_frame->kind() == TranslatedFrame::kArgumentsAdaptor) {
2672 parameter_count = parameter_frame->height() - 1; // Ignore the receiver.
2673 } else {
2674 parameter_frame = frame_it;
2675 parameter_count =
2676 frame_it->shared_info()->internal_formal_parameter_count();
2677 }
2678 TranslatedFrame::iterator parameter_it = parameter_frame->begin();
2679 parameter_it++; // Skip the function.
2680 parameter_it++; // Skip the receiver.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002681
Ben Murdoch097c5b22016-05-18 11:27:45 +01002682 // Figure out whether there is a construct stub frame on top of
2683 // the parameter frame.
2684 has_construct_stub_ =
2685 parameter_frame != state->begin() &&
2686 (parameter_frame - 1)->kind() == TranslatedFrame::kConstructStub;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002687
Ben Murdoch097c5b22016-05-18 11:27:45 +01002688 source_position_ =
2689 ComputeSourcePosition(frame_it->shared_info(), frame_it->node_id());
2690
2691 TranslatedFrame::iterator value_it = frame_it->begin();
2692 // Get the function. Note that this might materialize the function.
2693 // In case the debugger mutates this value, we should deoptimize
2694 // the function and remember the value in the materialized value store.
2695 function_ = Handle<JSFunction>::cast(value_it->GetValue());
2696
2697 parameters_.resize(static_cast<size_t>(parameter_count));
2698 for (int i = 0; i < parameter_count; i++) {
2699 Handle<Object> parameter = GetValueForDebugger(parameter_it, isolate);
2700 SetParameter(i, parameter);
2701 parameter_it++;
2702 }
2703
2704 // Skip the function, the receiver and the arguments.
2705 int skip_count =
2706 frame_it->shared_info()->internal_formal_parameter_count() + 2;
2707 TranslatedFrame::iterator stack_it = frame_it->begin();
2708 for (int i = 0; i < skip_count; i++) {
2709 stack_it++;
2710 }
2711
2712 // Get the context.
2713 context_ = GetValueForDebugger(stack_it, isolate);
2714 stack_it++;
2715
2716 // Get the expression stack.
2717 int stack_height = frame_it->height();
2718 if (frame_it->kind() == TranslatedFrame::kFunction ||
2719 frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
2720 // For full-code frames, we should not count the context.
2721 // For interpreter frames, we should not count the accumulator.
2722 // TODO(jarin): Clean up the indexing in translated frames.
2723 stack_height--;
2724 }
2725 expression_stack_.resize(static_cast<size_t>(stack_height));
2726 for (int i = 0; i < stack_height; i++) {
2727 Handle<Object> expression = GetValueForDebugger(stack_it, isolate);
2728 SetExpression(i, expression);
2729 stack_it++;
2730 }
2731
2732 // For interpreter frame, skip the accumulator.
2733 if (frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
2734 stack_it++;
2735 }
2736 CHECK(stack_it == frame_it->end());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002737}
2738
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002739
2740const char* Deoptimizer::GetDeoptReason(DeoptReason deopt_reason) {
2741 DCHECK(deopt_reason < kLastDeoptReason);
2742#define DEOPT_MESSAGES_TEXTS(C, T) T,
2743 static const char* deopt_messages_[] = {
2744 DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_TEXTS)};
2745#undef DEOPT_MESSAGES_TEXTS
2746 return deopt_messages_[deopt_reason];
2747}
2748
2749
2750Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code* code, Address pc) {
2751 SourcePosition last_position = SourcePosition::Unknown();
2752 Deoptimizer::DeoptReason last_reason = Deoptimizer::kNoReason;
2753 int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) |
2754 RelocInfo::ModeMask(RelocInfo::POSITION);
2755 for (RelocIterator it(code, mask); !it.done(); it.next()) {
2756 RelocInfo* info = it.rinfo();
2757 if (info->pc() >= pc) return DeoptInfo(last_position, NULL, last_reason);
2758 if (info->rmode() == RelocInfo::POSITION) {
2759 int raw_position = static_cast<int>(info->data());
2760 last_position = raw_position ? SourcePosition::FromRaw(raw_position)
2761 : SourcePosition::Unknown();
2762 } else if (info->rmode() == RelocInfo::DEOPT_REASON) {
2763 last_reason = static_cast<Deoptimizer::DeoptReason>(info->data());
2764 }
2765 }
2766 return DeoptInfo(SourcePosition::Unknown(), NULL, Deoptimizer::kNoReason);
2767}
2768
2769
2770// static
2771TranslatedValue TranslatedValue::NewArgumentsObject(TranslatedState* container,
2772 int length,
2773 int object_index) {
2774 TranslatedValue slot(container, kArgumentsObject);
2775 slot.materialization_info_ = {object_index, length};
2776 return slot;
2777}
2778
2779
2780// static
2781TranslatedValue TranslatedValue::NewDeferredObject(TranslatedState* container,
2782 int length,
2783 int object_index) {
2784 TranslatedValue slot(container, kCapturedObject);
2785 slot.materialization_info_ = {object_index, length};
2786 return slot;
2787}
2788
2789
2790// static
2791TranslatedValue TranslatedValue::NewDuplicateObject(TranslatedState* container,
2792 int id) {
2793 TranslatedValue slot(container, kDuplicatedObject);
2794 slot.materialization_info_ = {id, -1};
2795 return slot;
2796}
2797
2798
2799// static
2800TranslatedValue TranslatedValue::NewDouble(TranslatedState* container,
2801 double value) {
2802 TranslatedValue slot(container, kDouble);
2803 slot.double_value_ = value;
2804 return slot;
2805}
2806
2807
2808// static
2809TranslatedValue TranslatedValue::NewInt32(TranslatedState* container,
2810 int32_t value) {
2811 TranslatedValue slot(container, kInt32);
2812 slot.int32_value_ = value;
2813 return slot;
2814}
2815
2816
2817// static
2818TranslatedValue TranslatedValue::NewUInt32(TranslatedState* container,
2819 uint32_t value) {
2820 TranslatedValue slot(container, kUInt32);
2821 slot.uint32_value_ = value;
2822 return slot;
2823}
2824
2825
2826// static
2827TranslatedValue TranslatedValue::NewBool(TranslatedState* container,
2828 uint32_t value) {
2829 TranslatedValue slot(container, kBoolBit);
2830 slot.uint32_value_ = value;
2831 return slot;
2832}
2833
2834
2835// static
2836TranslatedValue TranslatedValue::NewTagged(TranslatedState* container,
2837 Object* literal) {
2838 TranslatedValue slot(container, kTagged);
2839 slot.raw_literal_ = literal;
2840 return slot;
2841}
2842
2843
2844// static
2845TranslatedValue TranslatedValue::NewInvalid(TranslatedState* container) {
2846 return TranslatedValue(container, kInvalid);
2847}
2848
2849
2850Isolate* TranslatedValue::isolate() const { return container_->isolate(); }
2851
2852
2853Object* TranslatedValue::raw_literal() const {
2854 DCHECK_EQ(kTagged, kind());
2855 return raw_literal_;
2856}
2857
2858
2859int32_t TranslatedValue::int32_value() const {
2860 DCHECK_EQ(kInt32, kind());
2861 return int32_value_;
2862}
2863
2864
2865uint32_t TranslatedValue::uint32_value() const {
2866 DCHECK(kind() == kUInt32 || kind() == kBoolBit);
2867 return uint32_value_;
2868}
2869
2870
2871double TranslatedValue::double_value() const {
2872 DCHECK_EQ(kDouble, kind());
2873 return double_value_;
2874}
2875
2876
2877int TranslatedValue::object_length() const {
2878 DCHECK(kind() == kArgumentsObject || kind() == kCapturedObject);
2879 return materialization_info_.length_;
2880}
2881
2882
2883int TranslatedValue::object_index() const {
2884 DCHECK(kind() == kArgumentsObject || kind() == kCapturedObject ||
2885 kind() == kDuplicatedObject);
2886 return materialization_info_.id_;
2887}
2888
2889
2890Object* TranslatedValue::GetRawValue() const {
2891 // If we have a value, return it.
2892 Handle<Object> result_handle;
2893 if (value_.ToHandle(&result_handle)) {
2894 return *result_handle;
2895 }
2896
2897 // Otherwise, do a best effort to get the value without allocation.
2898 switch (kind()) {
2899 case kTagged:
2900 return raw_literal();
2901
2902 case kInt32: {
2903 bool is_smi = Smi::IsValid(int32_value());
2904 if (is_smi) {
2905 return Smi::FromInt(int32_value());
2906 }
2907 break;
2908 }
2909
2910 case kUInt32: {
2911 bool is_smi = (uint32_value() <= static_cast<uintptr_t>(Smi::kMaxValue));
2912 if (is_smi) {
2913 return Smi::FromInt(static_cast<int32_t>(uint32_value()));
2914 }
2915 break;
2916 }
2917
2918 case kBoolBit: {
2919 if (uint32_value() == 0) {
2920 return isolate()->heap()->false_value();
2921 } else {
2922 CHECK_EQ(1U, uint32_value());
2923 return isolate()->heap()->true_value();
2924 }
2925 }
2926
2927 default:
2928 break;
2929 }
2930
2931 // If we could not get the value without allocation, return the arguments
2932 // marker.
2933 return isolate()->heap()->arguments_marker();
2934}
2935
2936
2937Handle<Object> TranslatedValue::GetValue() {
2938 Handle<Object> result;
2939 // If we already have a value, then get it.
2940 if (value_.ToHandle(&result)) return result;
2941
2942 // Otherwise we have to materialize.
2943 switch (kind()) {
2944 case TranslatedValue::kTagged:
2945 case TranslatedValue::kInt32:
2946 case TranslatedValue::kUInt32:
2947 case TranslatedValue::kBoolBit:
2948 case TranslatedValue::kDouble: {
2949 MaterializeSimple();
2950 return value_.ToHandleChecked();
2951 }
2952
2953 case TranslatedValue::kArgumentsObject:
2954 case TranslatedValue::kCapturedObject:
2955 case TranslatedValue::kDuplicatedObject:
2956 return container_->MaterializeObjectAt(object_index());
2957
2958 case TranslatedValue::kInvalid:
2959 FATAL("unexpected case");
2960 return Handle<Object>::null();
2961 }
2962
2963 FATAL("internal error: value missing");
2964 return Handle<Object>::null();
2965}
2966
2967
2968void TranslatedValue::MaterializeSimple() {
2969 // If we already have materialized, return.
2970 if (!value_.is_null()) return;
2971
2972 Object* raw_value = GetRawValue();
2973 if (raw_value != isolate()->heap()->arguments_marker()) {
2974 // We can get the value without allocation, just return it here.
2975 value_ = Handle<Object>(raw_value, isolate());
2976 return;
2977 }
2978
2979 switch (kind()) {
2980 case kInt32: {
2981 value_ = Handle<Object>(isolate()->factory()->NewNumber(int32_value()));
2982 return;
2983 }
2984
2985 case kUInt32:
2986 value_ = Handle<Object>(isolate()->factory()->NewNumber(uint32_value()));
2987 return;
2988
2989 case kDouble:
2990 value_ = Handle<Object>(isolate()->factory()->NewNumber(double_value()));
2991 return;
2992
2993 case kCapturedObject:
2994 case kDuplicatedObject:
2995 case kArgumentsObject:
2996 case kInvalid:
2997 case kTagged:
2998 case kBoolBit:
2999 FATAL("internal error: unexpected materialization.");
3000 break;
3001 }
3002}
3003
3004
3005bool TranslatedValue::IsMaterializedObject() const {
3006 switch (kind()) {
3007 case kCapturedObject:
3008 case kDuplicatedObject:
3009 case kArgumentsObject:
3010 return true;
3011 default:
3012 return false;
3013 }
3014}
3015
Ben Murdoch097c5b22016-05-18 11:27:45 +01003016bool TranslatedValue::IsMaterializableByDebugger() const {
3017 // At the moment, we only allow materialization of doubles.
3018 return (kind() == kDouble);
3019}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003020
3021int TranslatedValue::GetChildrenCount() const {
3022 if (kind() == kCapturedObject || kind() == kArgumentsObject) {
3023 return object_length();
3024 } else {
3025 return 0;
3026 }
3027}
3028
3029
3030uint32_t TranslatedState::GetUInt32Slot(Address fp, int slot_offset) {
3031 Address address = fp + slot_offset;
3032#if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT
3033 return Memory::uint32_at(address + kIntSize);
3034#else
3035 return Memory::uint32_at(address);
3036#endif
3037}
3038
3039
3040void TranslatedValue::Handlify() {
3041 if (kind() == kTagged) {
3042 value_ = Handle<Object>(raw_literal(), isolate());
3043 raw_literal_ = nullptr;
3044 }
3045}
3046
3047
3048TranslatedFrame TranslatedFrame::JSFrame(BailoutId node_id,
3049 SharedFunctionInfo* shared_info,
3050 int height) {
3051 TranslatedFrame frame(kFunction, shared_info->GetIsolate(), shared_info,
3052 height);
3053 frame.node_id_ = node_id;
3054 return frame;
3055}
3056
3057
3058TranslatedFrame TranslatedFrame::InterpretedFrame(
3059 BailoutId bytecode_offset, SharedFunctionInfo* shared_info, int height) {
3060 TranslatedFrame frame(kInterpretedFunction, shared_info->GetIsolate(),
3061 shared_info, height);
3062 frame.node_id_ = bytecode_offset;
3063 return frame;
3064}
3065
3066
3067TranslatedFrame TranslatedFrame::AccessorFrame(
3068 Kind kind, SharedFunctionInfo* shared_info) {
3069 DCHECK(kind == kSetter || kind == kGetter);
3070 return TranslatedFrame(kind, shared_info->GetIsolate(), shared_info);
3071}
3072
3073
3074TranslatedFrame TranslatedFrame::ArgumentsAdaptorFrame(
3075 SharedFunctionInfo* shared_info, int height) {
3076 return TranslatedFrame(kArgumentsAdaptor, shared_info->GetIsolate(),
3077 shared_info, height);
3078}
3079
Ben Murdochda12d292016-06-02 14:46:10 +01003080TranslatedFrame TranslatedFrame::TailCallerFrame(
3081 SharedFunctionInfo* shared_info) {
3082 return TranslatedFrame(kTailCallerFunction, shared_info->GetIsolate(),
3083 shared_info, 0);
3084}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003085
3086TranslatedFrame TranslatedFrame::ConstructStubFrame(
3087 SharedFunctionInfo* shared_info, int height) {
3088 return TranslatedFrame(kConstructStub, shared_info->GetIsolate(), shared_info,
3089 height);
3090}
3091
3092
3093int TranslatedFrame::GetValueCount() {
3094 switch (kind()) {
3095 case kFunction: {
3096 int parameter_count =
3097 raw_shared_info_->internal_formal_parameter_count() + 1;
3098 // + 1 for function.
3099 return height_ + parameter_count + 1;
3100 }
3101
3102 case kInterpretedFunction: {
3103 int parameter_count =
3104 raw_shared_info_->internal_formal_parameter_count() + 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +01003105 // + 2 for function and context.
3106 return height_ + parameter_count + 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003107 }
3108
3109 case kGetter:
3110 return 2; // Function and receiver.
3111
3112 case kSetter:
3113 return 3; // Function, receiver and the value to set.
3114
3115 case kArgumentsAdaptor:
3116 case kConstructStub:
3117 return 1 + height_;
3118
Ben Murdochda12d292016-06-02 14:46:10 +01003119 case kTailCallerFunction:
3120 return 1; // Function.
3121
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003122 case kCompiledStub:
3123 return height_;
3124
3125 case kInvalid:
3126 UNREACHABLE();
3127 break;
3128 }
3129 UNREACHABLE();
3130 return -1;
3131}
3132
3133
3134void TranslatedFrame::Handlify() {
3135 if (raw_shared_info_ != nullptr) {
3136 shared_info_ = Handle<SharedFunctionInfo>(raw_shared_info_);
3137 raw_shared_info_ = nullptr;
3138 }
3139 for (auto& value : values_) {
3140 value.Handlify();
3141 }
3142}
3143
3144
3145TranslatedFrame TranslatedState::CreateNextTranslatedFrame(
3146 TranslationIterator* iterator, FixedArray* literal_array, Address fp,
3147 FILE* trace_file) {
3148 Translation::Opcode opcode =
3149 static_cast<Translation::Opcode>(iterator->Next());
3150 switch (opcode) {
3151 case Translation::JS_FRAME: {
3152 BailoutId node_id = BailoutId(iterator->Next());
3153 SharedFunctionInfo* shared_info =
3154 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3155 int height = iterator->Next();
3156 if (trace_file != nullptr) {
3157 base::SmartArrayPointer<char> name =
3158 shared_info->DebugName()->ToCString();
3159 PrintF(trace_file, " reading input frame %s", name.get());
3160 int arg_count = shared_info->internal_formal_parameter_count() + 1;
3161 PrintF(trace_file, " => node=%d, args=%d, height=%d; inputs:\n",
3162 node_id.ToInt(), arg_count, height);
3163 }
3164 return TranslatedFrame::JSFrame(node_id, shared_info, height);
3165 }
3166
3167 case Translation::INTERPRETED_FRAME: {
3168 BailoutId bytecode_offset = BailoutId(iterator->Next());
3169 SharedFunctionInfo* shared_info =
3170 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3171 int height = iterator->Next();
3172 if (trace_file != nullptr) {
3173 base::SmartArrayPointer<char> name =
3174 shared_info->DebugName()->ToCString();
3175 PrintF(trace_file, " reading input frame %s", name.get());
3176 int arg_count = shared_info->internal_formal_parameter_count() + 1;
3177 PrintF(trace_file,
3178 " => bytecode_offset=%d, args=%d, height=%d; inputs:\n",
3179 bytecode_offset.ToInt(), arg_count, height);
3180 }
3181 return TranslatedFrame::InterpretedFrame(bytecode_offset, shared_info,
3182 height);
3183 }
3184
3185 case Translation::ARGUMENTS_ADAPTOR_FRAME: {
3186 SharedFunctionInfo* shared_info =
3187 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3188 int height = iterator->Next();
3189 if (trace_file != nullptr) {
3190 base::SmartArrayPointer<char> name =
3191 shared_info->DebugName()->ToCString();
3192 PrintF(trace_file, " reading arguments adaptor frame %s", name.get());
3193 PrintF(trace_file, " => height=%d; inputs:\n", height);
3194 }
3195 return TranslatedFrame::ArgumentsAdaptorFrame(shared_info, height);
3196 }
3197
Ben Murdochda12d292016-06-02 14:46:10 +01003198 case Translation::TAIL_CALLER_FRAME: {
3199 SharedFunctionInfo* shared_info =
3200 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3201 if (trace_file != nullptr) {
3202 base::SmartArrayPointer<char> name =
3203 shared_info->DebugName()->ToCString();
3204 PrintF(trace_file, " reading tail caller frame marker %s\n",
3205 name.get());
3206 }
3207 return TranslatedFrame::TailCallerFrame(shared_info);
3208 }
3209
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003210 case Translation::CONSTRUCT_STUB_FRAME: {
3211 SharedFunctionInfo* shared_info =
3212 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3213 int height = iterator->Next();
3214 if (trace_file != nullptr) {
3215 base::SmartArrayPointer<char> name =
3216 shared_info->DebugName()->ToCString();
3217 PrintF(trace_file, " reading construct stub frame %s", name.get());
3218 PrintF(trace_file, " => height=%d; inputs:\n", height);
3219 }
3220 return TranslatedFrame::ConstructStubFrame(shared_info, height);
3221 }
3222
3223 case Translation::GETTER_STUB_FRAME: {
3224 SharedFunctionInfo* shared_info =
3225 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3226 if (trace_file != nullptr) {
3227 base::SmartArrayPointer<char> name =
3228 shared_info->DebugName()->ToCString();
3229 PrintF(trace_file, " reading getter frame %s; inputs:\n", name.get());
3230 }
3231 return TranslatedFrame::AccessorFrame(TranslatedFrame::kGetter,
3232 shared_info);
3233 }
3234
3235 case Translation::SETTER_STUB_FRAME: {
3236 SharedFunctionInfo* shared_info =
3237 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
3238 if (trace_file != nullptr) {
3239 base::SmartArrayPointer<char> name =
3240 shared_info->DebugName()->ToCString();
3241 PrintF(trace_file, " reading setter frame %s; inputs:\n", name.get());
3242 }
3243 return TranslatedFrame::AccessorFrame(TranslatedFrame::kSetter,
3244 shared_info);
3245 }
3246
3247 case Translation::COMPILED_STUB_FRAME: {
3248 int height = iterator->Next();
3249 if (trace_file != nullptr) {
3250 PrintF(trace_file,
3251 " reading compiler stub frame => height=%d; inputs:\n", height);
3252 }
3253 return TranslatedFrame::CompiledStubFrame(height,
3254 literal_array->GetIsolate());
3255 }
3256
3257 case Translation::BEGIN:
3258 case Translation::DUPLICATED_OBJECT:
3259 case Translation::ARGUMENTS_OBJECT:
3260 case Translation::CAPTURED_OBJECT:
3261 case Translation::REGISTER:
3262 case Translation::INT32_REGISTER:
3263 case Translation::UINT32_REGISTER:
3264 case Translation::BOOL_REGISTER:
3265 case Translation::DOUBLE_REGISTER:
3266 case Translation::STACK_SLOT:
3267 case Translation::INT32_STACK_SLOT:
3268 case Translation::UINT32_STACK_SLOT:
3269 case Translation::BOOL_STACK_SLOT:
3270 case Translation::DOUBLE_STACK_SLOT:
3271 case Translation::LITERAL:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003272 break;
3273 }
3274 FATAL("We should never get here - unexpected deopt info.");
3275 return TranslatedFrame::InvalidFrame();
3276}
3277
3278
3279// static
3280void TranslatedFrame::AdvanceIterator(
3281 std::deque<TranslatedValue>::iterator* iter) {
3282 int values_to_skip = 1;
3283 while (values_to_skip > 0) {
3284 // Consume the current element.
3285 values_to_skip--;
3286 // Add all the children.
3287 values_to_skip += (*iter)->GetChildrenCount();
3288
3289 (*iter)++;
3290 }
3291}
3292
3293
3294// We can't intermix stack decoding and allocations because
3295// deoptimization infrastracture is not GC safe.
3296// Thus we build a temporary structure in malloced space.
3297TranslatedValue TranslatedState::CreateNextTranslatedValue(
3298 int frame_index, int value_index, TranslationIterator* iterator,
3299 FixedArray* literal_array, Address fp, RegisterValues* registers,
3300 FILE* trace_file) {
3301 disasm::NameConverter converter;
3302
3303 Translation::Opcode opcode =
3304 static_cast<Translation::Opcode>(iterator->Next());
3305 switch (opcode) {
3306 case Translation::BEGIN:
3307 case Translation::JS_FRAME:
3308 case Translation::INTERPRETED_FRAME:
3309 case Translation::ARGUMENTS_ADAPTOR_FRAME:
Ben Murdochda12d292016-06-02 14:46:10 +01003310 case Translation::TAIL_CALLER_FRAME:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003311 case Translation::CONSTRUCT_STUB_FRAME:
3312 case Translation::GETTER_STUB_FRAME:
3313 case Translation::SETTER_STUB_FRAME:
3314 case Translation::COMPILED_STUB_FRAME:
3315 // Peeled off before getting here.
3316 break;
3317
3318 case Translation::DUPLICATED_OBJECT: {
3319 int object_id = iterator->Next();
3320 if (trace_file != nullptr) {
3321 PrintF(trace_file, "duplicated object #%d", object_id);
3322 }
3323 object_positions_.push_back(object_positions_[object_id]);
3324 return TranslatedValue::NewDuplicateObject(this, object_id);
3325 }
3326
3327 case Translation::ARGUMENTS_OBJECT: {
3328 int arg_count = iterator->Next();
3329 int object_index = static_cast<int>(object_positions_.size());
3330 if (trace_file != nullptr) {
3331 PrintF(trace_file, "argumets object #%d (length = %d)", object_index,
3332 arg_count);
3333 }
3334 object_positions_.push_back({frame_index, value_index});
3335 return TranslatedValue::NewArgumentsObject(this, arg_count, object_index);
3336 }
3337
3338 case Translation::CAPTURED_OBJECT: {
3339 int field_count = iterator->Next();
3340 int object_index = static_cast<int>(object_positions_.size());
3341 if (trace_file != nullptr) {
3342 PrintF(trace_file, "captured object #%d (length = %d)", object_index,
3343 field_count);
3344 }
3345 object_positions_.push_back({frame_index, value_index});
3346 return TranslatedValue::NewDeferredObject(this, field_count,
3347 object_index);
3348 }
3349
3350 case Translation::REGISTER: {
3351 int input_reg = iterator->Next();
3352 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3353 intptr_t value = registers->GetRegister(input_reg);
3354 if (trace_file != nullptr) {
3355 PrintF(trace_file, "0x%08" V8PRIxPTR " ; %s ", value,
3356 converter.NameOfCPURegister(input_reg));
3357 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3358 }
3359 return TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value));
3360 }
3361
3362 case Translation::INT32_REGISTER: {
3363 int input_reg = iterator->Next();
3364 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3365 intptr_t value = registers->GetRegister(input_reg);
3366 if (trace_file != nullptr) {
3367 PrintF(trace_file, "%" V8PRIdPTR " ; %s ", value,
3368 converter.NameOfCPURegister(input_reg));
3369 }
3370 return TranslatedValue::NewInt32(this, static_cast<int32_t>(value));
3371 }
3372
3373 case Translation::UINT32_REGISTER: {
3374 int input_reg = iterator->Next();
3375 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3376 intptr_t value = registers->GetRegister(input_reg);
3377 if (trace_file != nullptr) {
3378 PrintF(trace_file, "%" V8PRIuPTR " ; %s (uint)", value,
3379 converter.NameOfCPURegister(input_reg));
3380 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3381 }
3382 return TranslatedValue::NewUInt32(this, static_cast<uint32_t>(value));
3383 }
3384
3385 case Translation::BOOL_REGISTER: {
3386 int input_reg = iterator->Next();
3387 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3388 intptr_t value = registers->GetRegister(input_reg);
3389 if (trace_file != nullptr) {
3390 PrintF(trace_file, "%" V8PRIdPTR " ; %s (bool)", value,
3391 converter.NameOfCPURegister(input_reg));
3392 }
3393 return TranslatedValue::NewBool(this, static_cast<uint32_t>(value));
3394 }
3395
3396 case Translation::DOUBLE_REGISTER: {
3397 int input_reg = iterator->Next();
3398 if (registers == nullptr) return TranslatedValue::NewInvalid(this);
3399 double value = registers->GetDoubleRegister(input_reg);
3400 if (trace_file != nullptr) {
3401 PrintF(trace_file, "%e ; %s (bool)", value,
3402 DoubleRegister::from_code(input_reg).ToString());
3403 }
3404 return TranslatedValue::NewDouble(this, value);
3405 }
3406
3407 case Translation::STACK_SLOT: {
3408 int slot_offset =
3409 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3410 intptr_t value = *(reinterpret_cast<intptr_t*>(fp + slot_offset));
3411 if (trace_file != nullptr) {
3412 PrintF(trace_file, "0x%08" V8PRIxPTR " ; [fp %c %d] ", value,
3413 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3414 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3415 }
3416 return TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value));
3417 }
3418
3419 case Translation::INT32_STACK_SLOT: {
3420 int slot_offset =
3421 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3422 uint32_t value = GetUInt32Slot(fp, slot_offset);
3423 if (trace_file != nullptr) {
3424 PrintF(trace_file, "%d ; (int) [fp %c %d] ",
3425 static_cast<int32_t>(value), slot_offset < 0 ? '-' : '+',
3426 std::abs(slot_offset));
3427 }
3428 return TranslatedValue::NewInt32(this, value);
3429 }
3430
3431 case Translation::UINT32_STACK_SLOT: {
3432 int slot_offset =
3433 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3434 uint32_t value = GetUInt32Slot(fp, slot_offset);
3435 if (trace_file != nullptr) {
3436 PrintF(trace_file, "%u ; (uint) [fp %c %d] ", value,
3437 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3438 }
3439 return TranslatedValue::NewUInt32(this, value);
3440 }
3441
3442 case Translation::BOOL_STACK_SLOT: {
3443 int slot_offset =
3444 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3445 uint32_t value = GetUInt32Slot(fp, slot_offset);
3446 if (trace_file != nullptr) {
3447 PrintF(trace_file, "%u ; (bool) [fp %c %d] ", value,
3448 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3449 }
3450 return TranslatedValue::NewBool(this, value);
3451 }
3452
3453 case Translation::DOUBLE_STACK_SLOT: {
3454 int slot_offset =
3455 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3456 double value = ReadDoubleValue(fp + slot_offset);
3457 if (trace_file != nullptr) {
3458 PrintF(trace_file, "%e ; (double) [fp %c %d] ", value,
3459 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3460 }
3461 return TranslatedValue::NewDouble(this, value);
3462 }
3463
3464 case Translation::LITERAL: {
3465 int literal_index = iterator->Next();
3466 Object* value = literal_array->get(literal_index);
3467 if (trace_file != nullptr) {
3468 PrintF(trace_file, "0x%08" V8PRIxPTR " ; (literal %d) ",
3469 reinterpret_cast<intptr_t>(value), literal_index);
3470 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3471 }
3472
3473 return TranslatedValue::NewTagged(this, value);
3474 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003475 }
3476
3477 FATAL("We should never get here - unexpected deopt info.");
3478 return TranslatedValue(nullptr, TranslatedValue::kInvalid);
3479}
3480
3481
3482TranslatedState::TranslatedState(JavaScriptFrame* frame)
3483 : isolate_(nullptr),
3484 stack_frame_pointer_(nullptr),
3485 has_adapted_arguments_(false) {
3486 int deopt_index = Safepoint::kNoDeoptimizationIndex;
3487 DeoptimizationInputData* data =
3488 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
3489 TranslationIterator it(data->TranslationByteArray(),
3490 data->TranslationIndex(deopt_index)->value());
3491 Init(frame->fp(), &it, data->LiteralArray(), nullptr /* registers */,
3492 nullptr /* trace file */);
3493}
3494
3495
3496TranslatedState::TranslatedState()
3497 : isolate_(nullptr),
3498 stack_frame_pointer_(nullptr),
3499 has_adapted_arguments_(false) {}
3500
3501
3502void TranslatedState::Init(Address input_frame_pointer,
3503 TranslationIterator* iterator,
3504 FixedArray* literal_array, RegisterValues* registers,
3505 FILE* trace_file) {
3506 DCHECK(frames_.empty());
3507
3508 isolate_ = literal_array->GetIsolate();
3509 // Read out the 'header' translation.
3510 Translation::Opcode opcode =
3511 static_cast<Translation::Opcode>(iterator->Next());
3512 CHECK(opcode == Translation::BEGIN);
3513
3514 int count = iterator->Next();
3515 iterator->Next(); // Drop JS frames count.
3516
3517 frames_.reserve(count);
3518
3519 std::stack<int> nested_counts;
3520
3521 // Read the frames
3522 for (int i = 0; i < count; i++) {
3523 // Read the frame descriptor.
3524 frames_.push_back(CreateNextTranslatedFrame(
3525 iterator, literal_array, input_frame_pointer, trace_file));
3526 TranslatedFrame& frame = frames_.back();
3527
3528 // Read the values.
3529 int values_to_process = frame.GetValueCount();
3530 while (values_to_process > 0 || !nested_counts.empty()) {
3531 if (trace_file != nullptr) {
3532 if (nested_counts.empty()) {
3533 // For top level values, print the value number.
3534 PrintF(trace_file, " %3i: ",
3535 frame.GetValueCount() - values_to_process);
3536 } else {
3537 // Take care of indenting for nested values.
3538 PrintF(trace_file, " ");
3539 for (size_t j = 0; j < nested_counts.size(); j++) {
3540 PrintF(trace_file, " ");
3541 }
3542 }
3543 }
3544
3545 TranslatedValue value = CreateNextTranslatedValue(
3546 i, static_cast<int>(frame.values_.size()), iterator, literal_array,
3547 input_frame_pointer, registers, trace_file);
3548 frame.Add(value);
3549
3550 if (trace_file != nullptr) {
3551 PrintF(trace_file, "\n");
3552 }
3553
3554 // Update the value count and resolve the nesting.
3555 values_to_process--;
3556 int children_count = value.GetChildrenCount();
3557 if (children_count > 0) {
3558 nested_counts.push(values_to_process);
3559 values_to_process = children_count;
3560 } else {
3561 while (values_to_process == 0 && !nested_counts.empty()) {
3562 values_to_process = nested_counts.top();
3563 nested_counts.pop();
3564 }
3565 }
3566 }
3567 }
3568
3569 CHECK(!iterator->HasNext() ||
3570 static_cast<Translation::Opcode>(iterator->Next()) ==
3571 Translation::BEGIN);
3572}
3573
3574
3575void TranslatedState::Prepare(bool has_adapted_arguments,
3576 Address stack_frame_pointer) {
3577 for (auto& frame : frames_) frame.Handlify();
3578
3579 stack_frame_pointer_ = stack_frame_pointer;
3580 has_adapted_arguments_ = has_adapted_arguments;
3581
3582 UpdateFromPreviouslyMaterializedObjects();
3583}
3584
3585
3586Handle<Object> TranslatedState::MaterializeAt(int frame_index,
3587 int* value_index) {
3588 TranslatedFrame* frame = &(frames_[frame_index]);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003589 CHECK(static_cast<size_t>(*value_index) < frame->values_.size());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003590
3591 TranslatedValue* slot = &(frame->values_[*value_index]);
3592 (*value_index)++;
3593
3594 switch (slot->kind()) {
3595 case TranslatedValue::kTagged:
3596 case TranslatedValue::kInt32:
3597 case TranslatedValue::kUInt32:
3598 case TranslatedValue::kBoolBit:
3599 case TranslatedValue::kDouble: {
3600 slot->MaterializeSimple();
3601 Handle<Object> value = slot->GetValue();
3602 if (value->IsMutableHeapNumber()) {
3603 HeapNumber::cast(*value)->set_map(isolate()->heap()->heap_number_map());
3604 }
3605 return value;
3606 }
3607
3608 case TranslatedValue::kArgumentsObject: {
3609 int length = slot->GetChildrenCount();
3610 Handle<JSObject> arguments;
3611 if (GetAdaptedArguments(&arguments, frame_index)) {
3612 // Store the materialized object and consume the nested values.
3613 for (int i = 0; i < length; ++i) {
3614 MaterializeAt(frame_index, value_index);
3615 }
3616 } else {
3617 Handle<JSFunction> function =
3618 Handle<JSFunction>::cast(frame->front().GetValue());
3619 arguments = isolate_->factory()->NewArgumentsObject(function, length);
3620 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
3621 DCHECK_EQ(array->length(), length);
3622 arguments->set_elements(*array);
3623 for (int i = 0; i < length; ++i) {
3624 Handle<Object> value = MaterializeAt(frame_index, value_index);
3625 array->set(i, *value);
3626 }
3627 }
3628 slot->value_ = arguments;
3629 return arguments;
3630 }
3631 case TranslatedValue::kCapturedObject: {
3632 int length = slot->GetChildrenCount();
3633
3634 // The map must be a tagged object.
3635 CHECK(frame->values_[*value_index].kind() == TranslatedValue::kTagged);
3636
3637 Handle<Object> result;
3638 if (slot->value_.ToHandle(&result)) {
3639 // This has been previously materialized, return the previous value.
3640 // We still need to skip all the nested objects.
3641 for (int i = 0; i < length; i++) {
3642 MaterializeAt(frame_index, value_index);
3643 }
3644
3645 return result;
3646 }
3647
3648 Handle<Object> map_object = MaterializeAt(frame_index, value_index);
3649 Handle<Map> map =
3650 Map::GeneralizeAllFieldRepresentations(Handle<Map>::cast(map_object));
3651 switch (map->instance_type()) {
3652 case MUTABLE_HEAP_NUMBER_TYPE:
3653 case HEAP_NUMBER_TYPE: {
3654 // Reuse the HeapNumber value directly as it is already properly
3655 // tagged and skip materializing the HeapNumber explicitly.
3656 Handle<Object> object = MaterializeAt(frame_index, value_index);
3657 slot->value_ = object;
3658 // On 32-bit architectures, there is an extra slot there because
3659 // the escape analysis calculates the number of slots as
3660 // object-size/pointer-size. To account for this, we read out
3661 // any extra slots.
3662 for (int i = 0; i < length - 2; i++) {
3663 MaterializeAt(frame_index, value_index);
3664 }
3665 return object;
3666 }
3667 case JS_OBJECT_TYPE: {
3668 Handle<JSObject> object =
3669 isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED);
3670 slot->value_ = object;
3671 Handle<Object> properties = MaterializeAt(frame_index, value_index);
3672 Handle<Object> elements = MaterializeAt(frame_index, value_index);
3673 object->set_properties(FixedArray::cast(*properties));
3674 object->set_elements(FixedArrayBase::cast(*elements));
3675 for (int i = 0; i < length - 3; ++i) {
3676 Handle<Object> value = MaterializeAt(frame_index, value_index);
3677 FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
3678 object->FastPropertyAtPut(index, *value);
3679 }
3680 return object;
3681 }
3682 case JS_ARRAY_TYPE: {
3683 Handle<JSArray> object =
3684 isolate_->factory()->NewJSArray(0, map->elements_kind());
3685 slot->value_ = object;
3686 Handle<Object> properties = MaterializeAt(frame_index, value_index);
3687 Handle<Object> elements = MaterializeAt(frame_index, value_index);
3688 Handle<Object> length = MaterializeAt(frame_index, value_index);
3689 object->set_properties(FixedArray::cast(*properties));
3690 object->set_elements(FixedArrayBase::cast(*elements));
3691 object->set_length(*length);
3692 return object;
3693 }
3694 case FIXED_ARRAY_TYPE: {
3695 Handle<Object> lengthObject = MaterializeAt(frame_index, value_index);
3696 int32_t length = 0;
3697 CHECK(lengthObject->ToInt32(&length));
3698 Handle<FixedArray> object =
3699 isolate_->factory()->NewFixedArray(length);
3700 // We need to set the map, because the fixed array we are
3701 // materializing could be a context or an arguments object,
3702 // in which case we must retain that information.
3703 object->set_map(*map);
3704 slot->value_ = object;
3705 for (int i = 0; i < length; ++i) {
3706 Handle<Object> value = MaterializeAt(frame_index, value_index);
3707 object->set(i, *value);
3708 }
3709 return object;
3710 }
3711 case FIXED_DOUBLE_ARRAY_TYPE: {
3712 DCHECK_EQ(*map, isolate_->heap()->fixed_double_array_map());
3713 Handle<Object> lengthObject = MaterializeAt(frame_index, value_index);
3714 int32_t length = 0;
3715 CHECK(lengthObject->ToInt32(&length));
3716 Handle<FixedArrayBase> object =
3717 isolate_->factory()->NewFixedDoubleArray(length);
3718 slot->value_ = object;
3719 if (length > 0) {
3720 Handle<FixedDoubleArray> double_array =
3721 Handle<FixedDoubleArray>::cast(object);
3722 for (int i = 0; i < length; ++i) {
3723 Handle<Object> value = MaterializeAt(frame_index, value_index);
3724 CHECK(value->IsNumber());
3725 double_array->set(i, value->Number());
3726 }
3727 }
3728 return object;
3729 }
3730 default:
3731 PrintF(stderr, "[couldn't handle instance type %d]\n",
3732 map->instance_type());
3733 FATAL("unreachable");
3734 return Handle<Object>::null();
3735 }
3736 UNREACHABLE();
3737 break;
3738 }
3739
3740 case TranslatedValue::kDuplicatedObject: {
3741 int object_index = slot->object_index();
3742 TranslatedState::ObjectPosition pos = object_positions_[object_index];
3743
3744 // Make sure the duplicate is refering to a previous object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003745 CHECK(pos.frame_index_ < frame_index ||
3746 (pos.frame_index_ == frame_index &&
3747 pos.value_index_ < *value_index - 1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003748
3749 Handle<Object> object =
3750 frames_[pos.frame_index_].values_[pos.value_index_].GetValue();
3751
3752 // The object should have a (non-sentinel) value.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003753 CHECK(!object.is_null() &&
3754 !object.is_identical_to(isolate_->factory()->arguments_marker()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003755
3756 slot->value_ = object;
3757 return object;
3758 }
3759
3760 case TranslatedValue::kInvalid:
3761 UNREACHABLE();
3762 break;
3763 }
3764
3765 FATAL("We should never get here - unexpected deopt slot kind.");
3766 return Handle<Object>::null();
3767}
3768
3769
3770Handle<Object> TranslatedState::MaterializeObjectAt(int object_index) {
3771 TranslatedState::ObjectPosition pos = object_positions_[object_index];
3772 return MaterializeAt(pos.frame_index_, &(pos.value_index_));
3773}
3774
3775
3776bool TranslatedState::GetAdaptedArguments(Handle<JSObject>* result,
3777 int frame_index) {
3778 if (frame_index == 0) {
3779 // Top level frame -> we need to go to the parent frame on the stack.
3780 if (!has_adapted_arguments_) return false;
3781
3782 // This is top level frame, so we need to go to the stack to get
3783 // this function's argument. (Note that this relies on not inlining
3784 // recursive functions!)
3785 Handle<JSFunction> function =
3786 Handle<JSFunction>::cast(frames_[frame_index].front().GetValue());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003787 *result = Accessors::FunctionGetArguments(function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003788 return true;
3789 } else {
3790 TranslatedFrame* previous_frame = &(frames_[frame_index]);
3791 if (previous_frame->kind() != TranslatedFrame::kArgumentsAdaptor) {
3792 return false;
3793 }
3794 // We get the adapted arguments from the parent translation.
3795 int length = previous_frame->height();
3796 Handle<JSFunction> function =
3797 Handle<JSFunction>::cast(previous_frame->front().GetValue());
3798 Handle<JSObject> arguments =
3799 isolate_->factory()->NewArgumentsObject(function, length);
3800 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
3801 arguments->set_elements(*array);
3802 TranslatedFrame::iterator arg_iterator = previous_frame->begin();
3803 arg_iterator++; // Skip function.
3804 for (int i = 0; i < length; ++i) {
3805 Handle<Object> value = arg_iterator->GetValue();
3806 array->set(i, *value);
3807 arg_iterator++;
3808 }
3809 CHECK(arg_iterator == previous_frame->end());
3810 *result = arguments;
3811 return true;
3812 }
3813}
3814
3815
3816TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex(
3817 int jsframe_index, int* args_count) {
3818 for (size_t i = 0; i < frames_.size(); i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003819 if (frames_[i].kind() == TranslatedFrame::kFunction ||
3820 frames_[i].kind() == TranslatedFrame::kInterpretedFunction) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003821 if (jsframe_index > 0) {
3822 jsframe_index--;
3823 } else {
3824 // We have the JS function frame, now check if it has arguments adaptor.
3825 if (i > 0 &&
3826 frames_[i - 1].kind() == TranslatedFrame::kArgumentsAdaptor) {
3827 *args_count = frames_[i - 1].height();
3828 return &(frames_[i - 1]);
3829 }
3830 *args_count =
3831 frames_[i].shared_info()->internal_formal_parameter_count() + 1;
3832 return &(frames_[i]);
3833 }
3834 }
3835 }
3836 return nullptr;
3837}
3838
3839
3840void TranslatedState::StoreMaterializedValuesAndDeopt() {
3841 MaterializedObjectStore* materialized_store =
3842 isolate_->materialized_object_store();
3843 Handle<FixedArray> previously_materialized_objects =
3844 materialized_store->Get(stack_frame_pointer_);
3845
3846 Handle<Object> marker = isolate_->factory()->arguments_marker();
3847
3848 int length = static_cast<int>(object_positions_.size());
3849 bool new_store = false;
3850 if (previously_materialized_objects.is_null()) {
3851 previously_materialized_objects =
3852 isolate_->factory()->NewFixedArray(length);
3853 for (int i = 0; i < length; i++) {
3854 previously_materialized_objects->set(i, *marker);
3855 }
3856 new_store = true;
3857 }
3858
Ben Murdoch097c5b22016-05-18 11:27:45 +01003859 CHECK_EQ(length, previously_materialized_objects->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003860
3861 bool value_changed = false;
3862 for (int i = 0; i < length; i++) {
3863 TranslatedState::ObjectPosition pos = object_positions_[i];
3864 TranslatedValue* value_info =
3865 &(frames_[pos.frame_index_].values_[pos.value_index_]);
3866
Ben Murdoch097c5b22016-05-18 11:27:45 +01003867 CHECK(value_info->IsMaterializedObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003868
3869 Handle<Object> value(value_info->GetRawValue(), isolate_);
3870
3871 if (!value.is_identical_to(marker)) {
3872 if (previously_materialized_objects->get(i) == *marker) {
3873 previously_materialized_objects->set(i, *value);
3874 value_changed = true;
3875 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003876 CHECK(previously_materialized_objects->get(i) == *value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003877 }
3878 }
3879 }
3880 if (new_store && value_changed) {
3881 materialized_store->Set(stack_frame_pointer_,
3882 previously_materialized_objects);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003883 CHECK(frames_[0].kind() == TranslatedFrame::kFunction ||
Ben Murdochda12d292016-06-02 14:46:10 +01003884 frames_[0].kind() == TranslatedFrame::kInterpretedFunction ||
3885 frames_[0].kind() == TranslatedFrame::kTailCallerFunction);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003886 Object* const function = frames_[0].front().GetRawValue();
3887 Deoptimizer::DeoptimizeFunction(JSFunction::cast(function));
3888 }
3889}
3890
3891
3892void TranslatedState::UpdateFromPreviouslyMaterializedObjects() {
3893 MaterializedObjectStore* materialized_store =
3894 isolate_->materialized_object_store();
3895 Handle<FixedArray> previously_materialized_objects =
3896 materialized_store->Get(stack_frame_pointer_);
3897
3898 // If we have no previously materialized objects, there is nothing to do.
3899 if (previously_materialized_objects.is_null()) return;
3900
3901 Handle<Object> marker = isolate_->factory()->arguments_marker();
3902
3903 int length = static_cast<int>(object_positions_.size());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003904 CHECK_EQ(length, previously_materialized_objects->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003905
3906 for (int i = 0; i < length; i++) {
3907 // For a previously materialized objects, inject their value into the
3908 // translated values.
3909 if (previously_materialized_objects->get(i) != *marker) {
3910 TranslatedState::ObjectPosition pos = object_positions_[i];
3911 TranslatedValue* value_info =
3912 &(frames_[pos.frame_index_].values_[pos.value_index_]);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003913 CHECK(value_info->IsMaterializedObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003914
3915 value_info->value_ =
3916 Handle<Object>(previously_materialized_objects->get(i), isolate_);
3917 }
3918 }
3919}
3920
3921} // namespace internal
3922} // namespace v8