~evarlast/ubuntu/utopic/mongodb/upstart-workaround-debian-bug-718702

« back to all changes in this revision

Viewing changes to src/third_party/v8/src/deoptimizer.cc

  • Committer: Package Import Robot
  • Author(s): James Page, James Page, Robie Basak
  • Date: 2013-05-29 17:44:42 UTC
  • mfrom: (44.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20130529174442-z0a4qmoww4y0t458
Tags: 1:2.4.3-1ubuntu1
[ James Page ]
* Merge from Debian unstable, remaining changes:
  - Enable SSL support:
    + d/control: Add libssl-dev to BD's.
    + d/rules: Enabled --ssl option.
    + d/mongodb.conf: Add example SSL configuration options.
  - d/mongodb-server.mongodb.upstart: Add upstart configuration.
  - d/rules: Don't strip binaries during scons build for Ubuntu.
  - d/control: Add armhf to target archs.
  - d/p/SConscript.client.patch: fixup install of client libraries.
  - d/p/0010-install-libs-to-usr-lib-not-usr-lib64-Closes-588557.patch:
    Install libraries to lib not lib64.
* Dropped changes:
  - d/p/arm-support.patch: Included in Debian.
  - d/p/double-alignment.patch: Included in Debian.
  - d/rules,control: Debian also builds with avaliable system libraries
    now.
* Fix FTBFS due to gcc and boost upgrades in saucy:
  - d/p/0008-ignore-unused-local-typedefs.patch: Add -Wno-unused-typedefs
    to unbreak building with g++-4.8.
  - d/p/0009-boost-1.53.patch: Fixup signed/unsigned casting issue.

[ Robie Basak ]
* d/p/0011-Use-a-signed-char-to-store-BSONType-enumerations.patch: Fixup
  build failure on ARM due to missing signed'ness of char cast.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2012 the V8 project authors. All rights reserved.
 
2
// Redistribution and use in source and binary forms, with or without
 
3
// modification, are permitted provided that the following conditions are
 
4
// met:
 
5
//
 
6
//     * Redistributions of source code must retain the above copyright
 
7
//       notice, this list of conditions and the following disclaimer.
 
8
//     * Redistributions in binary form must reproduce the above
 
9
//       copyright notice, this list of conditions and the following
 
10
//       disclaimer in the documentation and/or other materials provided
 
11
//       with the distribution.
 
12
//     * Neither the name of Google Inc. nor the names of its
 
13
//       contributors may be used to endorse or promote products derived
 
14
//       from this software without specific prior written permission.
 
15
//
 
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
27
 
 
28
#include "v8.h"
 
29
 
 
30
#include "codegen.h"
 
31
#include "deoptimizer.h"
 
32
#include "disasm.h"
 
33
#include "full-codegen.h"
 
34
#include "global-handles.h"
 
35
#include "macro-assembler.h"
 
36
#include "prettyprinter.h"
 
37
 
 
38
 
 
39
namespace v8 {
 
40
namespace internal {
 
41
 
 
42
DeoptimizerData::DeoptimizerData() {
 
43
  eager_deoptimization_entry_code_ = NULL;
 
44
  lazy_deoptimization_entry_code_ = NULL;
 
45
  current_ = NULL;
 
46
  deoptimizing_code_list_ = NULL;
 
47
#ifdef ENABLE_DEBUGGER_SUPPORT
 
48
  deoptimized_frame_info_ = NULL;
 
49
#endif
 
50
}
 
51
 
 
52
 
 
53
DeoptimizerData::~DeoptimizerData() {
 
54
  if (eager_deoptimization_entry_code_ != NULL) {
 
55
    Isolate::Current()->memory_allocator()->Free(
 
56
        eager_deoptimization_entry_code_);
 
57
    eager_deoptimization_entry_code_ = NULL;
 
58
  }
 
59
  if (lazy_deoptimization_entry_code_ != NULL) {
 
60
    Isolate::Current()->memory_allocator()->Free(
 
61
        lazy_deoptimization_entry_code_);
 
62
    lazy_deoptimization_entry_code_ = NULL;
 
63
  }
 
64
}
 
65
 
 
66
 
 
67
#ifdef ENABLE_DEBUGGER_SUPPORT
 
68
void DeoptimizerData::Iterate(ObjectVisitor* v) {
 
69
  if (deoptimized_frame_info_ != NULL) {
 
70
    deoptimized_frame_info_->Iterate(v);
 
71
  }
 
72
}
 
73
#endif
 
74
 
 
75
 
 
76
// We rely on this function not causing a GC.  It is called from generated code
 
77
// without having a real stack frame in place.
 
78
Deoptimizer* Deoptimizer::New(JSFunction* function,
 
79
                              BailoutType type,
 
80
                              unsigned bailout_id,
 
81
                              Address from,
 
82
                              int fp_to_sp_delta,
 
83
                              Isolate* isolate) {
 
84
  ASSERT(isolate == Isolate::Current());
 
85
  Deoptimizer* deoptimizer = new Deoptimizer(isolate,
 
86
                                             function,
 
87
                                             type,
 
88
                                             bailout_id,
 
89
                                             from,
 
90
                                             fp_to_sp_delta,
 
91
                                             NULL);
 
92
  ASSERT(isolate->deoptimizer_data()->current_ == NULL);
 
93
  isolate->deoptimizer_data()->current_ = deoptimizer;
 
94
  return deoptimizer;
 
95
}
 
96
 
 
97
 
 
98
Deoptimizer* Deoptimizer::Grab(Isolate* isolate) {
 
99
  ASSERT(isolate == Isolate::Current());
 
100
  Deoptimizer* result = isolate->deoptimizer_data()->current_;
 
101
  ASSERT(result != NULL);
 
102
  result->DeleteFrameDescriptions();
 
103
  isolate->deoptimizer_data()->current_ = NULL;
 
104
  return result;
 
105
}
 
106
 
 
107
 
 
108
int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) {
 
109
  if (jsframe_index == 0) return 0;
 
110
 
 
111
  int frame_index = 0;
 
112
  while (jsframe_index >= 0) {
 
113
    FrameDescription* frame = output_[frame_index];
 
114
    if (frame->GetFrameType() == StackFrame::JAVA_SCRIPT) {
 
115
      jsframe_index--;
 
116
    }
 
117
    frame_index++;
 
118
  }
 
119
 
 
120
  return frame_index - 1;
 
121
}
 
122
 
 
123
 
 
124
#ifdef ENABLE_DEBUGGER_SUPPORT
 
125
DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
 
126
    JavaScriptFrame* frame,
 
127
    int jsframe_index,
 
128
    Isolate* isolate) {
 
129
  ASSERT(isolate == Isolate::Current());
 
130
  ASSERT(frame->is_optimized());
 
131
  ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL);
 
132
 
 
133
  // Get the function and code from the frame.
 
134
  JSFunction* function = JSFunction::cast(frame->function());
 
135
  Code* code = frame->LookupCode();
 
136
 
 
137
  // Locate the deoptimization point in the code. As we are at a call the
 
138
  // return address must be at a place in the code with deoptimization support.
 
139
  SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc());
 
140
  int deoptimization_index = safepoint_entry.deoptimization_index();
 
141
  ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex);
 
142
 
 
143
  // Always use the actual stack slots when calculating the fp to sp
 
144
  // delta adding two for the function and context.
 
145
  unsigned stack_slots = code->stack_slots();
 
146
  unsigned fp_to_sp_delta = ((stack_slots + 2) * kPointerSize);
 
147
 
 
148
  Deoptimizer* deoptimizer = new Deoptimizer(isolate,
 
149
                                             function,
 
150
                                             Deoptimizer::DEBUGGER,
 
151
                                             deoptimization_index,
 
152
                                             frame->pc(),
 
153
                                             fp_to_sp_delta,
 
154
                                             code);
 
155
  Address tos = frame->fp() - fp_to_sp_delta;
 
156
  deoptimizer->FillInputFrame(tos, frame);
 
157
 
 
158
  // Calculate the output frames.
 
159
  Deoptimizer::ComputeOutputFrames(deoptimizer);
 
160
 
 
161
  // Create the GC safe output frame information and register it for GC
 
162
  // handling.
 
163
  ASSERT_LT(jsframe_index, deoptimizer->jsframe_count());
 
164
 
 
165
  // Convert JS frame index into frame index.
 
166
  int frame_index = deoptimizer->ConvertJSFrameIndexToFrameIndex(jsframe_index);
 
167
 
 
168
  bool has_arguments_adaptor =
 
169
      frame_index > 0 &&
 
170
      deoptimizer->output_[frame_index - 1]->GetFrameType() ==
 
171
      StackFrame::ARGUMENTS_ADAPTOR;
 
172
 
 
173
  int construct_offset = has_arguments_adaptor ? 2 : 1;
 
174
  bool has_construct_stub =
 
175
      frame_index >= construct_offset &&
 
176
      deoptimizer->output_[frame_index - construct_offset]->GetFrameType() ==
 
177
      StackFrame::CONSTRUCT;
 
178
 
 
179
  DeoptimizedFrameInfo* info = new DeoptimizedFrameInfo(deoptimizer,
 
180
                                                        frame_index,
 
181
                                                        has_arguments_adaptor,
 
182
                                                        has_construct_stub);
 
183
  isolate->deoptimizer_data()->deoptimized_frame_info_ = info;
 
184
 
 
185
  // Get the "simulated" top and size for the requested frame.
 
186
  FrameDescription* parameters_frame =
 
187
      deoptimizer->output_[
 
188
          has_arguments_adaptor ? (frame_index - 1) : frame_index];
 
189
 
 
190
  uint32_t parameters_size = (info->parameters_count() + 1) * kPointerSize;
 
191
  Address parameters_top = reinterpret_cast<Address>(
 
192
      parameters_frame->GetTop() + (parameters_frame->GetFrameSize() -
 
193
                                    parameters_size));
 
194
 
 
195
  uint32_t expressions_size = info->expression_count() * kPointerSize;
 
196
  Address expressions_top = reinterpret_cast<Address>(
 
197
      deoptimizer->output_[frame_index]->GetTop());
 
198
 
 
199
  // Done with the GC-unsafe frame descriptions. This re-enables allocation.
 
200
  deoptimizer->DeleteFrameDescriptions();
 
201
 
 
202
  // Allocate a heap number for the doubles belonging to this frame.
 
203
  deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame(
 
204
      parameters_top, parameters_size, expressions_top, expressions_size, info);
 
205
 
 
206
  // Finished using the deoptimizer instance.
 
207
  delete deoptimizer;
 
208
 
 
209
  return info;
 
210
}
 
211
 
 
212
 
 
213
void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
 
214
                                                 Isolate* isolate) {
 
215
  ASSERT(isolate == Isolate::Current());
 
216
  ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == info);
 
217
  delete info;
 
218
  isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL;
 
219
}
 
220
#endif
 
221
 
 
222
void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
 
223
                                                int count,
 
224
                                                BailoutType type) {
 
225
  TableEntryGenerator generator(masm, type, count);
 
226
  generator.Generate();
 
227
}
 
228
 
 
229
 
 
230
class DeoptimizingVisitor : public OptimizedFunctionVisitor {
 
231
 public:
 
232
  virtual void EnterContext(Context* context) {
 
233
    if (FLAG_trace_deopt) {
 
234
      PrintF("[deoptimize context: %" V8PRIxPTR "]\n",
 
235
             reinterpret_cast<intptr_t>(context));
 
236
    }
 
237
  }
 
238
 
 
239
  virtual void VisitFunction(JSFunction* function) {
 
240
    Deoptimizer::DeoptimizeFunction(function);
 
241
  }
 
242
 
 
243
  virtual void LeaveContext(Context* context) {
 
244
    context->ClearOptimizedFunctions();
 
245
  }
 
246
};
 
247
 
 
248
 
 
249
void Deoptimizer::DeoptimizeAll() {
 
250
  AssertNoAllocation no_allocation;
 
251
 
 
252
  if (FLAG_trace_deopt) {
 
253
    PrintF("[deoptimize all contexts]\n");
 
254
  }
 
255
 
 
256
  DeoptimizingVisitor visitor;
 
257
  VisitAllOptimizedFunctions(&visitor);
 
258
}
 
259
 
 
260
 
 
261
void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) {
 
262
  AssertNoAllocation no_allocation;
 
263
 
 
264
  DeoptimizingVisitor visitor;
 
265
  VisitAllOptimizedFunctionsForGlobalObject(object, &visitor);
 
266
}
 
267
 
 
268
 
 
269
void Deoptimizer::VisitAllOptimizedFunctionsForContext(
 
270
    Context* context, OptimizedFunctionVisitor* visitor) {
 
271
  Isolate* isolate = context->GetIsolate();
 
272
  ZoneScope zone_scope(isolate->runtime_zone(), DELETE_ON_EXIT);
 
273
  AssertNoAllocation no_allocation;
 
274
 
 
275
  ASSERT(context->IsGlobalContext());
 
276
 
 
277
  visitor->EnterContext(context);
 
278
 
 
279
  // Create a snapshot of the optimized functions list. This is needed because
 
280
  // visitors might remove more than one link from the list at once.
 
281
  ZoneList<JSFunction*> snapshot(1, isolate->runtime_zone());
 
282
  Object* element = context->OptimizedFunctionsListHead();
 
283
  while (!element->IsUndefined()) {
 
284
    JSFunction* element_function = JSFunction::cast(element);
 
285
    snapshot.Add(element_function, isolate->runtime_zone());
 
286
    element = element_function->next_function_link();
 
287
  }
 
288
 
 
289
  // Run through the snapshot of optimized functions and visit them.
 
290
  for (int i = 0; i < snapshot.length(); ++i) {
 
291
    visitor->VisitFunction(snapshot.at(i));
 
292
  }
 
293
 
 
294
  visitor->LeaveContext(context);
 
295
}
 
296
 
 
297
 
 
298
void Deoptimizer::VisitAllOptimizedFunctionsForGlobalObject(
 
299
    JSObject* object, OptimizedFunctionVisitor* visitor) {
 
300
  AssertNoAllocation no_allocation;
 
301
 
 
302
  if (object->IsJSGlobalProxy()) {
 
303
    Object* proto = object->GetPrototype();
 
304
    ASSERT(proto->IsJSGlobalObject());
 
305
    VisitAllOptimizedFunctionsForContext(
 
306
        GlobalObject::cast(proto)->global_context(), visitor);
 
307
  } else if (object->IsGlobalObject()) {
 
308
    VisitAllOptimizedFunctionsForContext(
 
309
        GlobalObject::cast(object)->global_context(), visitor);
 
310
  }
 
311
}
 
312
 
 
313
 
 
314
void Deoptimizer::VisitAllOptimizedFunctions(
 
315
    OptimizedFunctionVisitor* visitor) {
 
316
  AssertNoAllocation no_allocation;
 
317
 
 
318
  // Run through the list of all global contexts and deoptimize.
 
319
  Object* context = Isolate::Current()->heap()->global_contexts_list();
 
320
  while (!context->IsUndefined()) {
 
321
    // GC can happen when the context is not fully initialized,
 
322
    // so the global field of the context can be undefined.
 
323
    Object* global = Context::cast(context)->get(Context::GLOBAL_INDEX);
 
324
    if (!global->IsUndefined()) {
 
325
      VisitAllOptimizedFunctionsForGlobalObject(JSObject::cast(global),
 
326
                                                visitor);
 
327
    }
 
328
    context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
 
329
  }
 
330
}
 
331
 
 
332
 
 
333
void Deoptimizer::HandleWeakDeoptimizedCode(
 
334
    v8::Persistent<v8::Value> obj, void* data) {
 
335
  DeoptimizingCodeListNode* node =
 
336
      reinterpret_cast<DeoptimizingCodeListNode*>(data);
 
337
  RemoveDeoptimizingCode(*node->code());
 
338
#ifdef DEBUG
 
339
  node = Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_;
 
340
  while (node != NULL) {
 
341
    ASSERT(node != reinterpret_cast<DeoptimizingCodeListNode*>(data));
 
342
    node = node->next();
 
343
  }
 
344
#endif
 
345
}
 
346
 
 
347
 
 
348
void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) {
 
349
  deoptimizer->DoComputeOutputFrames();
 
350
}
 
351
 
 
352
 
 
353
Deoptimizer::Deoptimizer(Isolate* isolate,
 
354
                         JSFunction* function,
 
355
                         BailoutType type,
 
356
                         unsigned bailout_id,
 
357
                         Address from,
 
358
                         int fp_to_sp_delta,
 
359
                         Code* optimized_code)
 
360
    : isolate_(isolate),
 
361
      function_(function),
 
362
      bailout_id_(bailout_id),
 
363
      bailout_type_(type),
 
364
      from_(from),
 
365
      fp_to_sp_delta_(fp_to_sp_delta),
 
366
      has_alignment_padding_(0),
 
367
      input_(NULL),
 
368
      output_count_(0),
 
369
      jsframe_count_(0),
 
370
      output_(NULL),
 
371
      deferred_heap_numbers_(0) {
 
372
  if (FLAG_trace_deopt && type != OSR) {
 
373
    if (type == DEBUGGER) {
 
374
      PrintF("**** DEOPT FOR DEBUGGER: ");
 
375
    } else {
 
376
      PrintF("**** DEOPT: ");
 
377
    }
 
378
    function->PrintName();
 
379
    PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n",
 
380
           bailout_id,
 
381
           reinterpret_cast<intptr_t>(from),
 
382
           fp_to_sp_delta - (2 * kPointerSize));
 
383
  } else if (FLAG_trace_osr && type == OSR) {
 
384
    PrintF("**** OSR: ");
 
385
    function->PrintName();
 
386
    PrintF(" at ast id #%u, address 0x%" V8PRIxPTR ", frame size %d\n",
 
387
           bailout_id,
 
388
           reinterpret_cast<intptr_t>(from),
 
389
           fp_to_sp_delta - (2 * kPointerSize));
 
390
  }
 
391
  function->shared()->increment_deopt_count();
 
392
  // Find the optimized code.
 
393
  if (type == EAGER) {
 
394
    ASSERT(from == NULL);
 
395
    optimized_code_ = function_->code();
 
396
    if (FLAG_trace_deopt && FLAG_code_comments) {
 
397
      // Print instruction associated with this bailout.
 
398
      const char* last_comment = NULL;
 
399
      int mask = RelocInfo::ModeMask(RelocInfo::COMMENT)
 
400
          | RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
 
401
      for (RelocIterator it(optimized_code_, mask); !it.done(); it.next()) {
 
402
        RelocInfo* info = it.rinfo();
 
403
        if (info->rmode() == RelocInfo::COMMENT) {
 
404
          last_comment = reinterpret_cast<const char*>(info->data());
 
405
        }
 
406
        if (info->rmode() == RelocInfo::RUNTIME_ENTRY) {
 
407
          unsigned id = Deoptimizer::GetDeoptimizationId(
 
408
              info->target_address(), Deoptimizer::EAGER);
 
409
          if (id == bailout_id && last_comment != NULL) {
 
410
            PrintF("            %s\n", last_comment);
 
411
            break;
 
412
          }
 
413
        }
 
414
      }
 
415
    }
 
416
  } else if (type == LAZY) {
 
417
    optimized_code_ = FindDeoptimizingCodeFromAddress(from);
 
418
    ASSERT(optimized_code_ != NULL);
 
419
  } else if (type == OSR) {
 
420
    // The function has already been optimized and we're transitioning
 
421
    // from the unoptimized shared version to the optimized one in the
 
422
    // function. The return address (from) points to unoptimized code.
 
423
    optimized_code_ = function_->code();
 
424
    ASSERT(optimized_code_->kind() == Code::OPTIMIZED_FUNCTION);
 
425
    ASSERT(!optimized_code_->contains(from));
 
426
  } else if (type == DEBUGGER) {
 
427
    optimized_code_ = optimized_code;
 
428
    ASSERT(optimized_code_->contains(from));
 
429
  }
 
430
  ASSERT(HEAP->allow_allocation(false));
 
431
  unsigned size = ComputeInputFrameSize();
 
432
  input_ = new(size) FrameDescription(size, function);
 
433
  input_->SetFrameType(StackFrame::JAVA_SCRIPT);
 
434
}
 
435
 
 
436
 
 
437
Deoptimizer::~Deoptimizer() {
 
438
  ASSERT(input_ == NULL && output_ == NULL);
 
439
}
 
440
 
 
441
 
 
442
void Deoptimizer::DeleteFrameDescriptions() {
 
443
  delete input_;
 
444
  for (int i = 0; i < output_count_; ++i) {
 
445
    if (output_[i] != input_) delete output_[i];
 
446
  }
 
447
  delete[] output_;
 
448
  input_ = NULL;
 
449
  output_ = NULL;
 
450
  ASSERT(!HEAP->allow_allocation(true));
 
451
}
 
452
 
 
453
 
 
454
Address Deoptimizer::GetDeoptimizationEntry(int id, BailoutType type) {
 
455
  ASSERT(id >= 0);
 
456
  if (id >= kNumberOfEntries) return NULL;
 
457
  MemoryChunk* base = NULL;
 
458
  DeoptimizerData* data = Isolate::Current()->deoptimizer_data();
 
459
  if (type == EAGER) {
 
460
    if (data->eager_deoptimization_entry_code_ == NULL) {
 
461
      data->eager_deoptimization_entry_code_ = CreateCode(type);
 
462
    }
 
463
    base = data->eager_deoptimization_entry_code_;
 
464
  } else {
 
465
    if (data->lazy_deoptimization_entry_code_ == NULL) {
 
466
      data->lazy_deoptimization_entry_code_ = CreateCode(type);
 
467
    }
 
468
    base = data->lazy_deoptimization_entry_code_;
 
469
  }
 
470
  return
 
471
      static_cast<Address>(base->area_start()) + (id * table_entry_size_);
 
472
}
 
473
 
 
474
 
 
475
int Deoptimizer::GetDeoptimizationId(Address addr, BailoutType type) {
 
476
  MemoryChunk* base = NULL;
 
477
  DeoptimizerData* data = Isolate::Current()->deoptimizer_data();
 
478
  if (type == EAGER) {
 
479
    base = data->eager_deoptimization_entry_code_;
 
480
  } else {
 
481
    base = data->lazy_deoptimization_entry_code_;
 
482
  }
 
483
  if (base == NULL ||
 
484
      addr < base->area_start() ||
 
485
      addr >= base->area_start() +
 
486
          (kNumberOfEntries * table_entry_size_)) {
 
487
    return kNotDeoptimizationEntry;
 
488
  }
 
489
  ASSERT_EQ(0,
 
490
      static_cast<int>(addr - base->area_start()) % table_entry_size_);
 
491
  return static_cast<int>(addr - base->area_start()) / table_entry_size_;
 
492
}
 
493
 
 
494
 
 
495
int Deoptimizer::GetOutputInfo(DeoptimizationOutputData* data,
 
496
                               unsigned id,
 
497
                               SharedFunctionInfo* shared) {
 
498
  // TODO(kasperl): For now, we do a simple linear search for the PC
 
499
  // offset associated with the given node id. This should probably be
 
500
  // changed to a binary search.
 
501
  int length = data->DeoptPoints();
 
502
  Smi* smi_id = Smi::FromInt(id);
 
503
  for (int i = 0; i < length; i++) {
 
504
    if (data->AstId(i) == smi_id) {
 
505
      return data->PcAndState(i)->value();
 
506
    }
 
507
  }
 
508
  PrintF("[couldn't find pc offset for node=%u]\n", id);
 
509
  PrintF("[method: %s]\n", *shared->DebugName()->ToCString());
 
510
  // Print the source code if available.
 
511
  HeapStringAllocator string_allocator;
 
512
  StringStream stream(&string_allocator);
 
513
  shared->SourceCodePrint(&stream, -1);
 
514
  PrintF("[source:\n%s\n]", *stream.ToCString());
 
515
 
 
516
  UNREACHABLE();
 
517
  return -1;
 
518
}
 
519
 
 
520
 
 
521
int Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) {
 
522
  int length = 0;
 
523
  DeoptimizingCodeListNode* node =
 
524
      isolate->deoptimizer_data()->deoptimizing_code_list_;
 
525
  while (node != NULL) {
 
526
    length++;
 
527
    node = node->next();
 
528
  }
 
529
  return length;
 
530
}
 
531
 
 
532
 
 
533
// We rely on this function not causing a GC.  It is called from generated code
 
534
// without having a real stack frame in place.
 
535
void Deoptimizer::DoComputeOutputFrames() {
 
536
  if (bailout_type_ == OSR) {
 
537
    DoComputeOsrOutputFrame();
 
538
    return;
 
539
  }
 
540
 
 
541
  // Print some helpful diagnostic information.
 
542
  int64_t start = OS::Ticks();
 
543
  if (FLAG_trace_deopt) {
 
544
    PrintF("[deoptimizing%s: begin 0x%08" V8PRIxPTR " ",
 
545
           (bailout_type_ == LAZY ? " (lazy)" : ""),
 
546
           reinterpret_cast<intptr_t>(function_));
 
547
    function_->PrintName();
 
548
    PrintF(" @%d]\n", bailout_id_);
 
549
  }
 
550
 
 
551
  // Determine basic deoptimization information.  The optimized frame is
 
552
  // described by the input data.
 
553
  DeoptimizationInputData* input_data =
 
554
      DeoptimizationInputData::cast(optimized_code_->deoptimization_data());
 
555
  unsigned node_id = input_data->AstId(bailout_id_)->value();
 
556
  ByteArray* translations = input_data->TranslationByteArray();
 
557
  unsigned translation_index =
 
558
      input_data->TranslationIndex(bailout_id_)->value();
 
559
 
 
560
  // Do the input frame to output frame(s) translation.
 
561
  TranslationIterator iterator(translations, translation_index);
 
562
  Translation::Opcode opcode =
 
563
      static_cast<Translation::Opcode>(iterator.Next());
 
564
  ASSERT(Translation::BEGIN == opcode);
 
565
  USE(opcode);
 
566
  // Read the number of output frames and allocate an array for their
 
567
  // descriptions.
 
568
  int count = iterator.Next();
 
569
  iterator.Next();  // Drop JS frames count.
 
570
  ASSERT(output_ == NULL);
 
571
  output_ = new FrameDescription*[count];
 
572
  for (int i = 0; i < count; ++i) {
 
573
    output_[i] = NULL;
 
574
  }
 
575
  output_count_ = count;
 
576
 
 
577
  // Translate each output frame.
 
578
  for (int i = 0; i < count; ++i) {
 
579
    // Read the ast node id, function, and frame height for this output frame.
 
580
    Translation::Opcode opcode =
 
581
        static_cast<Translation::Opcode>(iterator.Next());
 
582
    switch (opcode) {
 
583
      case Translation::JS_FRAME:
 
584
        DoComputeJSFrame(&iterator, i);
 
585
        jsframe_count_++;
 
586
        break;
 
587
      case Translation::ARGUMENTS_ADAPTOR_FRAME:
 
588
        DoComputeArgumentsAdaptorFrame(&iterator, i);
 
589
        break;
 
590
      case Translation::CONSTRUCT_STUB_FRAME:
 
591
        DoComputeConstructStubFrame(&iterator, i);
 
592
        break;
 
593
      default:
 
594
        UNREACHABLE();
 
595
        break;
 
596
    }
 
597
  }
 
598
 
 
599
  // Print some helpful diagnostic information.
 
600
  if (FLAG_trace_deopt) {
 
601
    double ms = static_cast<double>(OS::Ticks() - start) / 1000;
 
602
    int index = output_count_ - 1;  // Index of the topmost frame.
 
603
    JSFunction* function = output_[index]->GetFunction();
 
604
    PrintF("[deoptimizing: end 0x%08" V8PRIxPTR " ",
 
605
           reinterpret_cast<intptr_t>(function));
 
606
    function->PrintName();
 
607
    PrintF(" => node=%u, pc=0x%08" V8PRIxPTR ", state=%s, alignment=%s,"
 
608
           " took %0.3f ms]\n",
 
609
           node_id,
 
610
           output_[index]->GetPc(),
 
611
           FullCodeGenerator::State2String(
 
612
               static_cast<FullCodeGenerator::State>(
 
613
                   output_[index]->GetState()->value())),
 
614
           has_alignment_padding_ ? "with padding" : "no padding",
 
615
           ms);
 
616
  }
 
617
}
 
618
 
 
619
 
 
620
void Deoptimizer::MaterializeHeapNumbers() {
 
621
  ASSERT_NE(DEBUGGER, bailout_type_);
 
622
  for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
 
623
    HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i];
 
624
    Handle<Object> num = isolate_->factory()->NewNumber(d.value());
 
625
    if (FLAG_trace_deopt) {
 
626
      PrintF("Materializing a new heap number %p [%e] in slot %p\n",
 
627
             reinterpret_cast<void*>(*num),
 
628
             d.value(),
 
629
             d.slot_address());
 
630
    }
 
631
 
 
632
    Memory::Object_at(d.slot_address()) = *num;
 
633
  }
 
634
}
 
635
 
 
636
 
 
637
#ifdef ENABLE_DEBUGGER_SUPPORT
 
638
void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
 
639
    Address parameters_top,
 
640
    uint32_t parameters_size,
 
641
    Address expressions_top,
 
642
    uint32_t expressions_size,
 
643
    DeoptimizedFrameInfo* info) {
 
644
  ASSERT_EQ(DEBUGGER, bailout_type_);
 
645
  Address parameters_bottom = parameters_top + parameters_size;
 
646
  Address expressions_bottom = expressions_top + expressions_size;
 
647
  for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
 
648
    HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i];
 
649
 
 
650
    // Check of the heap number to materialize actually belong to the frame
 
651
    // being extracted.
 
652
    Address slot = d.slot_address();
 
653
    if (parameters_top <= slot && slot < parameters_bottom) {
 
654
      Handle<Object> num = isolate_->factory()->NewNumber(d.value());
 
655
 
 
656
      int index = (info->parameters_count() - 1) -
 
657
          static_cast<int>(slot - parameters_top) / kPointerSize;
 
658
 
 
659
      if (FLAG_trace_deopt) {
 
660
        PrintF("Materializing a new heap number %p [%e] in slot %p"
 
661
               "for parameter slot #%d\n",
 
662
               reinterpret_cast<void*>(*num),
 
663
               d.value(),
 
664
               d.slot_address(),
 
665
               index);
 
666
      }
 
667
 
 
668
      info->SetParameter(index, *num);
 
669
    } else if (expressions_top <= slot && slot < expressions_bottom) {
 
670
      Handle<Object> num = isolate_->factory()->NewNumber(d.value());
 
671
 
 
672
      int index = info->expression_count() - 1 -
 
673
          static_cast<int>(slot - expressions_top) / kPointerSize;
 
674
 
 
675
      if (FLAG_trace_deopt) {
 
676
        PrintF("Materializing a new heap number %p [%e] in slot %p"
 
677
               "for expression slot #%d\n",
 
678
               reinterpret_cast<void*>(*num),
 
679
               d.value(),
 
680
               d.slot_address(),
 
681
               index);
 
682
      }
 
683
 
 
684
      info->SetExpression(index, *num);
 
685
    }
 
686
  }
 
687
}
 
688
#endif
 
689
 
 
690
 
 
691
void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
 
692
                                     int frame_index,
 
693
                                     unsigned output_offset) {
 
694
  disasm::NameConverter converter;
 
695
  // A GC-safe temporary placeholder that we can put in the output frame.
 
696
  const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0));
 
697
 
 
698
  // Ignore commands marked as duplicate and act on the first non-duplicate.
 
699
  Translation::Opcode opcode =
 
700
      static_cast<Translation::Opcode>(iterator->Next());
 
701
  while (opcode == Translation::DUPLICATE) {
 
702
    opcode = static_cast<Translation::Opcode>(iterator->Next());
 
703
    iterator->Skip(Translation::NumberOfOperandsFor(opcode));
 
704
    opcode = static_cast<Translation::Opcode>(iterator->Next());
 
705
  }
 
706
 
 
707
  switch (opcode) {
 
708
    case Translation::BEGIN:
 
709
    case Translation::JS_FRAME:
 
710
    case Translation::ARGUMENTS_ADAPTOR_FRAME:
 
711
    case Translation::CONSTRUCT_STUB_FRAME:
 
712
    case Translation::DUPLICATE:
 
713
      UNREACHABLE();
 
714
      return;
 
715
 
 
716
    case Translation::REGISTER: {
 
717
      int input_reg = iterator->Next();
 
718
      intptr_t input_value = input_->GetRegister(input_reg);
 
719
      if (FLAG_trace_deopt) {
 
720
        PrintF(
 
721
            "    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s ",
 
722
            output_[frame_index]->GetTop() + output_offset,
 
723
            output_offset,
 
724
            input_value,
 
725
            converter.NameOfCPURegister(input_reg));
 
726
        reinterpret_cast<Object*>(input_value)->ShortPrint();
 
727
        PrintF("\n");
 
728
      }
 
729
      output_[frame_index]->SetFrameSlot(output_offset, input_value);
 
730
      return;
 
731
    }
 
732
 
 
733
    case Translation::INT32_REGISTER: {
 
734
      int input_reg = iterator->Next();
 
735
      intptr_t value = input_->GetRegister(input_reg);
 
736
      bool is_smi = Smi::IsValid(value);
 
737
      if (FLAG_trace_deopt) {
 
738
        PrintF(
 
739
            "    0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIdPTR " ; %s (%s)\n",
 
740
            output_[frame_index]->GetTop() + output_offset,
 
741
            output_offset,
 
742
            value,
 
743
            converter.NameOfCPURegister(input_reg),
 
744
            is_smi ? "smi" : "heap number");
 
745
      }
 
746
      if (is_smi) {
 
747
        intptr_t tagged_value =
 
748
            reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
 
749
        output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
 
750
      } else {
 
751
        // We save the untagged value on the side and store a GC-safe
 
752
        // temporary placeholder in the frame.
 
753
        AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
 
754
                       static_cast<double>(static_cast<int32_t>(value)));
 
755
        output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
 
756
      }
 
757
      return;
 
758
    }
 
759
 
 
760
    case Translation::DOUBLE_REGISTER: {
 
761
      int input_reg = iterator->Next();
 
762
      double value = input_->GetDoubleRegister(input_reg);
 
763
      if (FLAG_trace_deopt) {
 
764
        PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- %e ; %s\n",
 
765
               output_[frame_index]->GetTop() + output_offset,
 
766
               output_offset,
 
767
               value,
 
768
               DoubleRegister::AllocationIndexToString(input_reg));
 
769
      }
 
770
      // We save the untagged value on the side and store a GC-safe
 
771
      // temporary placeholder in the frame.
 
772
      AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value);
 
773
      output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
 
774
      return;
 
775
    }
 
776
 
 
777
    case Translation::STACK_SLOT: {
 
778
      int input_slot_index = iterator->Next();
 
779
      unsigned input_offset =
 
780
          input_->GetOffsetFromSlotIndex(input_slot_index);
 
781
      intptr_t input_value = input_->GetFrameSlot(input_offset);
 
782
      if (FLAG_trace_deopt) {
 
783
        PrintF("    0x%08" V8PRIxPTR ": ",
 
784
               output_[frame_index]->GetTop() + output_offset);
 
785
        PrintF("[top + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ",
 
786
               output_offset,
 
787
               input_value,
 
788
               input_offset);
 
789
        reinterpret_cast<Object*>(input_value)->ShortPrint();
 
790
        PrintF("\n");
 
791
      }
 
792
      output_[frame_index]->SetFrameSlot(output_offset, input_value);
 
793
      return;
 
794
    }
 
795
 
 
796
    case Translation::INT32_STACK_SLOT: {
 
797
      int input_slot_index = iterator->Next();
 
798
      unsigned input_offset =
 
799
          input_->GetOffsetFromSlotIndex(input_slot_index);
 
800
      intptr_t value = input_->GetFrameSlot(input_offset);
 
801
      bool is_smi = Smi::IsValid(value);
 
802
      if (FLAG_trace_deopt) {
 
803
        PrintF("    0x%08" V8PRIxPTR ": ",
 
804
               output_[frame_index]->GetTop() + output_offset);
 
805
        PrintF("[top + %d] <- %" V8PRIdPTR " ; [sp + %d] (%s)\n",
 
806
               output_offset,
 
807
               value,
 
808
               input_offset,
 
809
               is_smi ? "smi" : "heap number");
 
810
      }
 
811
      if (is_smi) {
 
812
        intptr_t tagged_value =
 
813
            reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
 
814
        output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
 
815
      } else {
 
816
        // We save the untagged value on the side and store a GC-safe
 
817
        // temporary placeholder in the frame.
 
818
        AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
 
819
                       static_cast<double>(static_cast<int32_t>(value)));
 
820
        output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
 
821
      }
 
822
      return;
 
823
    }
 
824
 
 
825
    case Translation::DOUBLE_STACK_SLOT: {
 
826
      int input_slot_index = iterator->Next();
 
827
      unsigned input_offset =
 
828
          input_->GetOffsetFromSlotIndex(input_slot_index);
 
829
      double value = input_->GetDoubleFrameSlot(input_offset);
 
830
      if (FLAG_trace_deopt) {
 
831
        PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- %e ; [sp + %d]\n",
 
832
               output_[frame_index]->GetTop() + output_offset,
 
833
               output_offset,
 
834
               value,
 
835
               input_offset);
 
836
      }
 
837
      // We save the untagged value on the side and store a GC-safe
 
838
      // temporary placeholder in the frame.
 
839
      AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value);
 
840
      output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
 
841
      return;
 
842
    }
 
843
 
 
844
    case Translation::LITERAL: {
 
845
      Object* literal = ComputeLiteral(iterator->Next());
 
846
      if (FLAG_trace_deopt) {
 
847
        PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- ",
 
848
               output_[frame_index]->GetTop() + output_offset,
 
849
               output_offset);
 
850
        literal->ShortPrint();
 
851
        PrintF(" ; literal\n");
 
852
      }
 
853
      intptr_t value = reinterpret_cast<intptr_t>(literal);
 
854
      output_[frame_index]->SetFrameSlot(output_offset, value);
 
855
      return;
 
856
    }
 
857
 
 
858
    case Translation::ARGUMENTS_OBJECT: {
 
859
      // Use the arguments marker value as a sentinel and fill in the arguments
 
860
      // object after the deoptimized frame is built.
 
861
      if (FLAG_trace_deopt) {
 
862
        PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- ",
 
863
               output_[frame_index]->GetTop() + output_offset,
 
864
               output_offset);
 
865
        isolate_->heap()->arguments_marker()->ShortPrint();
 
866
        PrintF(" ; arguments object\n");
 
867
      }
 
868
      intptr_t value = reinterpret_cast<intptr_t>(
 
869
          isolate_->heap()->arguments_marker());
 
870
      output_[frame_index]->SetFrameSlot(output_offset, value);
 
871
      return;
 
872
    }
 
873
  }
 
874
}
 
875
 
 
876
 
 
877
bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,
 
878
                                        int* input_offset) {
 
879
  disasm::NameConverter converter;
 
880
  FrameDescription* output = output_[0];
 
881
 
 
882
  // The input values are all part of the unoptimized frame so they
 
883
  // are all tagged pointers.
 
884
  uintptr_t input_value = input_->GetFrameSlot(*input_offset);
 
885
  Object* input_object = reinterpret_cast<Object*>(input_value);
 
886
 
 
887
  Translation::Opcode opcode =
 
888
      static_cast<Translation::Opcode>(iterator->Next());
 
889
  bool duplicate = (opcode == Translation::DUPLICATE);
 
890
  if (duplicate) {
 
891
    opcode = static_cast<Translation::Opcode>(iterator->Next());
 
892
  }
 
893
 
 
894
  switch (opcode) {
 
895
    case Translation::BEGIN:
 
896
    case Translation::JS_FRAME:
 
897
    case Translation::ARGUMENTS_ADAPTOR_FRAME:
 
898
    case Translation::CONSTRUCT_STUB_FRAME:
 
899
    case Translation::DUPLICATE:
 
900
      UNREACHABLE();  // Malformed input.
 
901
       return false;
 
902
 
 
903
     case Translation::REGISTER: {
 
904
       int output_reg = iterator->Next();
 
905
       if (FLAG_trace_osr) {
 
906
         PrintF("    %s <- 0x%08" V8PRIxPTR " ; [sp + %d]\n",
 
907
                converter.NameOfCPURegister(output_reg),
 
908
                input_value,
 
909
                *input_offset);
 
910
       }
 
911
       output->SetRegister(output_reg, input_value);
 
912
       break;
 
913
     }
 
914
 
 
915
    case Translation::INT32_REGISTER: {
 
916
      // Abort OSR if we don't have a number.
 
917
      if (!input_object->IsNumber()) return false;
 
918
 
 
919
      int output_reg = iterator->Next();
 
920
      int int32_value = input_object->IsSmi()
 
921
          ? Smi::cast(input_object)->value()
 
922
          : FastD2I(input_object->Number());
 
923
      // Abort the translation if the conversion lost information.
 
924
      if (!input_object->IsSmi() &&
 
925
          FastI2D(int32_value) != input_object->Number()) {
 
926
        if (FLAG_trace_osr) {
 
927
          PrintF("**** %g could not be converted to int32 ****\n",
 
928
                 input_object->Number());
 
929
        }
 
930
        return false;
 
931
      }
 
932
      if (FLAG_trace_osr) {
 
933
        PrintF("    %s <- %d (int32) ; [sp + %d]\n",
 
934
               converter.NameOfCPURegister(output_reg),
 
935
               int32_value,
 
936
               *input_offset);
 
937
      }
 
938
      output->SetRegister(output_reg, int32_value);
 
939
      break;
 
940
    }
 
941
 
 
942
    case Translation::DOUBLE_REGISTER: {
 
943
      // Abort OSR if we don't have a number.
 
944
      if (!input_object->IsNumber()) return false;
 
945
 
 
946
      int output_reg = iterator->Next();
 
947
      double double_value = input_object->Number();
 
948
      if (FLAG_trace_osr) {
 
949
        PrintF("    %s <- %g (double) ; [sp + %d]\n",
 
950
               DoubleRegister::AllocationIndexToString(output_reg),
 
951
               double_value,
 
952
               *input_offset);
 
953
      }
 
954
      output->SetDoubleRegister(output_reg, double_value);
 
955
      break;
 
956
    }
 
957
 
 
958
    case Translation::STACK_SLOT: {
 
959
      int output_index = iterator->Next();
 
960
      unsigned output_offset =
 
961
          output->GetOffsetFromSlotIndex(output_index);
 
962
      if (FLAG_trace_osr) {
 
963
        PrintF("    [sp + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ",
 
964
               output_offset,
 
965
               input_value,
 
966
               *input_offset);
 
967
        reinterpret_cast<Object*>(input_value)->ShortPrint();
 
968
        PrintF("\n");
 
969
      }
 
970
      output->SetFrameSlot(output_offset, input_value);
 
971
      break;
 
972
    }
 
973
 
 
974
    case Translation::INT32_STACK_SLOT: {
 
975
      // Abort OSR if we don't have a number.
 
976
      if (!input_object->IsNumber()) return false;
 
977
 
 
978
      int output_index = iterator->Next();
 
979
      unsigned output_offset =
 
980
          output->GetOffsetFromSlotIndex(output_index);
 
981
      int int32_value = input_object->IsSmi()
 
982
          ? Smi::cast(input_object)->value()
 
983
          : DoubleToInt32(input_object->Number());
 
984
      // Abort the translation if the conversion lost information.
 
985
      if (!input_object->IsSmi() &&
 
986
          FastI2D(int32_value) != input_object->Number()) {
 
987
        if (FLAG_trace_osr) {
 
988
          PrintF("**** %g could not be converted to int32 ****\n",
 
989
                 input_object->Number());
 
990
        }
 
991
        return false;
 
992
      }
 
993
      if (FLAG_trace_osr) {
 
994
        PrintF("    [sp + %d] <- %d (int32) ; [sp + %d]\n",
 
995
               output_offset,
 
996
               int32_value,
 
997
               *input_offset);
 
998
      }
 
999
      output->SetFrameSlot(output_offset, int32_value);
 
1000
      break;
 
1001
    }
 
1002
 
 
1003
    case Translation::DOUBLE_STACK_SLOT: {
 
1004
      static const int kLowerOffset = 0 * kPointerSize;
 
1005
      static const int kUpperOffset = 1 * kPointerSize;
 
1006
 
 
1007
      // Abort OSR if we don't have a number.
 
1008
      if (!input_object->IsNumber()) return false;
 
1009
 
 
1010
      int output_index = iterator->Next();
 
1011
      unsigned output_offset =
 
1012
          output->GetOffsetFromSlotIndex(output_index);
 
1013
      double double_value = input_object->Number();
 
1014
      uint64_t int_value = BitCast<uint64_t, double>(double_value);
 
1015
      int32_t lower = static_cast<int32_t>(int_value);
 
1016
      int32_t upper = static_cast<int32_t>(int_value >> kBitsPerInt);
 
1017
      if (FLAG_trace_osr) {
 
1018
        PrintF("    [sp + %d] <- 0x%08x (upper bits of %g) ; [sp + %d]\n",
 
1019
               output_offset + kUpperOffset,
 
1020
               upper,
 
1021
               double_value,
 
1022
               *input_offset);
 
1023
        PrintF("    [sp + %d] <- 0x%08x (lower bits of %g) ; [sp + %d]\n",
 
1024
               output_offset + kLowerOffset,
 
1025
               lower,
 
1026
               double_value,
 
1027
               *input_offset);
 
1028
      }
 
1029
      output->SetFrameSlot(output_offset + kLowerOffset, lower);
 
1030
      output->SetFrameSlot(output_offset + kUpperOffset, upper);
 
1031
      break;
 
1032
    }
 
1033
 
 
1034
    case Translation::LITERAL: {
 
1035
      // Just ignore non-materialized literals.
 
1036
      iterator->Next();
 
1037
      break;
 
1038
    }
 
1039
 
 
1040
    case Translation::ARGUMENTS_OBJECT: {
 
1041
      // Optimized code assumes that the argument object has not been
 
1042
      // materialized and so bypasses it when doing arguments access.
 
1043
      // We should have bailed out before starting the frame
 
1044
      // translation.
 
1045
      UNREACHABLE();
 
1046
      return false;
 
1047
    }
 
1048
  }
 
1049
 
 
1050
  if (!duplicate) *input_offset -= kPointerSize;
 
1051
  return true;
 
1052
}
 
1053
 
 
1054
 
 
1055
void Deoptimizer::PatchStackCheckCode(Code* unoptimized_code,
 
1056
                                      Code* check_code,
 
1057
                                      Code* replacement_code) {
 
1058
  // Iterate over the stack check table and patch every stack check
 
1059
  // call to an unconditional call to the replacement code.
 
1060
  ASSERT(unoptimized_code->kind() == Code::FUNCTION);
 
1061
  Address stack_check_cursor = unoptimized_code->instruction_start() +
 
1062
      unoptimized_code->stack_check_table_offset();
 
1063
  uint32_t table_length = Memory::uint32_at(stack_check_cursor);
 
1064
  stack_check_cursor += kIntSize;
 
1065
  for (uint32_t i = 0; i < table_length; ++i) {
 
1066
    uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize);
 
1067
    Address pc_after = unoptimized_code->instruction_start() + pc_offset;
 
1068
    PatchStackCheckCodeAt(unoptimized_code,
 
1069
                          pc_after,
 
1070
                          check_code,
 
1071
                          replacement_code);
 
1072
    stack_check_cursor += 2 * kIntSize;
 
1073
  }
 
1074
}
 
1075
 
 
1076
 
 
1077
void Deoptimizer::RevertStackCheckCode(Code* unoptimized_code,
 
1078
                                       Code* check_code,
 
1079
                                       Code* replacement_code) {
 
1080
  // Iterate over the stack check table and revert the patched
 
1081
  // stack check calls.
 
1082
  ASSERT(unoptimized_code->kind() == Code::FUNCTION);
 
1083
  Address stack_check_cursor = unoptimized_code->instruction_start() +
 
1084
      unoptimized_code->stack_check_table_offset();
 
1085
  uint32_t table_length = Memory::uint32_at(stack_check_cursor);
 
1086
  stack_check_cursor += kIntSize;
 
1087
  for (uint32_t i = 0; i < table_length; ++i) {
 
1088
    uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize);
 
1089
    Address pc_after = unoptimized_code->instruction_start() + pc_offset;
 
1090
    RevertStackCheckCodeAt(unoptimized_code,
 
1091
                           pc_after,
 
1092
                           check_code,
 
1093
                           replacement_code);
 
1094
    stack_check_cursor += 2 * kIntSize;
 
1095
  }
 
1096
}
 
1097
 
 
1098
 
 
1099
unsigned Deoptimizer::ComputeInputFrameSize() const {
 
1100
  unsigned fixed_size = ComputeFixedSize(function_);
 
1101
  // The fp-to-sp delta already takes the context and the function
 
1102
  // into account so we have to avoid double counting them (-2).
 
1103
  unsigned result = fixed_size + fp_to_sp_delta_ - (2 * kPointerSize);
 
1104
#ifdef DEBUG
 
1105
  if (bailout_type_ == OSR) {
 
1106
    // TODO(kasperl): It would be nice if we could verify that the
 
1107
    // size matches with the stack height we can compute based on the
 
1108
    // environment at the OSR entry. The code for that his built into
 
1109
    // the DoComputeOsrOutputFrame function for now.
 
1110
  } else {
 
1111
    unsigned stack_slots = optimized_code_->stack_slots();
 
1112
    unsigned outgoing_size = ComputeOutgoingArgumentSize();
 
1113
    ASSERT(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size);
 
1114
  }
 
1115
#endif
 
1116
  return result;
 
1117
}
 
1118
 
 
1119
 
 
1120
unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const {
 
1121
  // The fixed part of the frame consists of the return address, frame
 
1122
  // pointer, function, context, and all the incoming arguments.
 
1123
  return ComputeIncomingArgumentSize(function) +
 
1124
      StandardFrameConstants::kFixedFrameSize;
 
1125
}
 
1126
 
 
1127
 
 
1128
unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const {
 
1129
  // The incoming arguments is the values for formal parameters and
 
1130
  // the receiver. Every slot contains a pointer.
 
1131
  unsigned arguments = function->shared()->formal_parameter_count() + 1;
 
1132
  return arguments * kPointerSize;
 
1133
}
 
1134
 
 
1135
 
 
1136
unsigned Deoptimizer::ComputeOutgoingArgumentSize() const {
 
1137
  DeoptimizationInputData* data = DeoptimizationInputData::cast(
 
1138
      optimized_code_->deoptimization_data());
 
1139
  unsigned height = data->ArgumentsStackHeight(bailout_id_)->value();
 
1140
  return height * kPointerSize;
 
1141
}
 
1142
 
 
1143
 
 
1144
Object* Deoptimizer::ComputeLiteral(int index) const {
 
1145
  DeoptimizationInputData* data = DeoptimizationInputData::cast(
 
1146
      optimized_code_->deoptimization_data());
 
1147
  FixedArray* literals = data->LiteralArray();
 
1148
  return literals->get(index);
 
1149
}
 
1150
 
 
1151
 
 
1152
void Deoptimizer::AddDoubleValue(intptr_t slot_address,
 
1153
                                 double value) {
 
1154
  HeapNumberMaterializationDescriptor value_desc(
 
1155
      reinterpret_cast<Address>(slot_address), value);
 
1156
  deferred_heap_numbers_.Add(value_desc);
 
1157
}
 
1158
 
 
1159
 
 
1160
MemoryChunk* Deoptimizer::CreateCode(BailoutType type) {
 
1161
  // We cannot run this if the serializer is enabled because this will
 
1162
  // cause us to emit relocation information for the external
 
1163
  // references. This is fine because the deoptimizer's code section
 
1164
  // isn't meant to be serialized at all.
 
1165
  ASSERT(!Serializer::enabled());
 
1166
 
 
1167
  MacroAssembler masm(Isolate::Current(), NULL, 16 * KB);
 
1168
  masm.set_emit_debug_code(false);
 
1169
  GenerateDeoptimizationEntries(&masm, kNumberOfEntries, type);
 
1170
  CodeDesc desc;
 
1171
  masm.GetCode(&desc);
 
1172
  ASSERT(desc.reloc_size == 0);
 
1173
 
 
1174
  MemoryChunk* chunk =
 
1175
      Isolate::Current()->memory_allocator()->AllocateChunk(desc.instr_size,
 
1176
                                                            EXECUTABLE,
 
1177
                                                            NULL);
 
1178
  ASSERT(chunk->area_size() >= desc.instr_size);
 
1179
  if (chunk == NULL) {
 
1180
    V8::FatalProcessOutOfMemory("Not enough memory for deoptimization table");
 
1181
  }
 
1182
  memcpy(chunk->area_start(), desc.buffer, desc.instr_size);
 
1183
  CPU::FlushICache(chunk->area_start(), desc.instr_size);
 
1184
  return chunk;
 
1185
}
 
1186
 
 
1187
 
 
1188
Code* Deoptimizer::FindDeoptimizingCodeFromAddress(Address addr) {
 
1189
  DeoptimizingCodeListNode* node =
 
1190
      Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_;
 
1191
  while (node != NULL) {
 
1192
    if (node->code()->contains(addr)) return *node->code();
 
1193
    node = node->next();
 
1194
  }
 
1195
  return NULL;
 
1196
}
 
1197
 
 
1198
 
 
1199
void Deoptimizer::RemoveDeoptimizingCode(Code* code) {
 
1200
  DeoptimizerData* data = Isolate::Current()->deoptimizer_data();
 
1201
  ASSERT(data->deoptimizing_code_list_ != NULL);
 
1202
  // Run through the code objects to find this one and remove it.
 
1203
  DeoptimizingCodeListNode* prev = NULL;
 
1204
  DeoptimizingCodeListNode* current = data->deoptimizing_code_list_;
 
1205
  while (current != NULL) {
 
1206
    if (*current->code() == code) {
 
1207
      // Unlink from list. If prev is NULL we are looking at the first element.
 
1208
      if (prev == NULL) {
 
1209
        data->deoptimizing_code_list_ = current->next();
 
1210
      } else {
 
1211
        prev->set_next(current->next());
 
1212
      }
 
1213
      delete current;
 
1214
      return;
 
1215
    }
 
1216
    // Move to next in list.
 
1217
    prev = current;
 
1218
    current = current->next();
 
1219
  }
 
1220
  // Deoptimizing code is removed through weak callback. Each object is expected
 
1221
  // to be removed once and only once.
 
1222
  UNREACHABLE();
 
1223
}
 
1224
 
 
1225
 
 
1226
FrameDescription::FrameDescription(uint32_t frame_size,
 
1227
                                   JSFunction* function)
 
1228
    : frame_size_(frame_size),
 
1229
      function_(function),
 
1230
      top_(kZapUint32),
 
1231
      pc_(kZapUint32),
 
1232
      fp_(kZapUint32),
 
1233
      context_(kZapUint32) {
 
1234
  // Zap all the registers.
 
1235
  for (int r = 0; r < Register::kNumRegisters; r++) {
 
1236
    SetRegister(r, kZapUint32);
 
1237
  }
 
1238
 
 
1239
  // Zap all the slots.
 
1240
  for (unsigned o = 0; o < frame_size; o += kPointerSize) {
 
1241
    SetFrameSlot(o, kZapUint32);
 
1242
  }
 
1243
}
 
1244
 
 
1245
 
 
1246
int FrameDescription::ComputeFixedSize() {
 
1247
  return StandardFrameConstants::kFixedFrameSize +
 
1248
      (ComputeParametersCount() + 1) * kPointerSize;
 
1249
}
 
1250
 
 
1251
 
 
1252
unsigned FrameDescription::GetOffsetFromSlotIndex(int slot_index) {
 
1253
  if (slot_index >= 0) {
 
1254
    // Local or spill slots. Skip the fixed part of the frame
 
1255
    // including all arguments.
 
1256
    unsigned base = GetFrameSize() - ComputeFixedSize();
 
1257
    return base - ((slot_index + 1) * kPointerSize);
 
1258
  } else {
 
1259
    // Incoming parameter.
 
1260
    int arg_size = (ComputeParametersCount() + 1) * kPointerSize;
 
1261
    unsigned base = GetFrameSize() - arg_size;
 
1262
    return base - ((slot_index + 1) * kPointerSize);
 
1263
  }
 
1264
}
 
1265
 
 
1266
 
 
1267
int FrameDescription::ComputeParametersCount() {
 
1268
  switch (type_) {
 
1269
    case StackFrame::JAVA_SCRIPT:
 
1270
      return function_->shared()->formal_parameter_count();
 
1271
    case StackFrame::ARGUMENTS_ADAPTOR: {
 
1272
      // Last slot contains number of incomming arguments as a smi.
 
1273
      // Can't use GetExpression(0) because it would cause infinite recursion.
 
1274
      return reinterpret_cast<Smi*>(*GetFrameSlotPointer(0))->value();
 
1275
    }
 
1276
    default:
 
1277
      UNREACHABLE();
 
1278
      return 0;
 
1279
  }
 
1280
}
 
1281
 
 
1282
 
 
1283
Object* FrameDescription::GetParameter(int index) {
 
1284
  ASSERT(index >= 0);
 
1285
  ASSERT(index < ComputeParametersCount());
 
1286
  // The slot indexes for incoming arguments are negative.
 
1287
  unsigned offset = GetOffsetFromSlotIndex(index - ComputeParametersCount());
 
1288
  return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset));
 
1289
}
 
1290
 
 
1291
 
 
1292
unsigned FrameDescription::GetExpressionCount() {
 
1293
  ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_);
 
1294
  unsigned size = GetFrameSize() - ComputeFixedSize();
 
1295
  return size / kPointerSize;
 
1296
}
 
1297
 
 
1298
 
 
1299
Object* FrameDescription::GetExpression(int index) {
 
1300
  ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_);
 
1301
  unsigned offset = GetOffsetFromSlotIndex(index);
 
1302
  return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset));
 
1303
}
 
1304
 
 
1305
 
 
1306
void TranslationBuffer::Add(int32_t value, Zone* zone) {
 
1307
  // Encode the sign bit in the least significant bit.
 
1308
  bool is_negative = (value < 0);
 
1309
  uint32_t bits = ((is_negative ? -value : value) << 1) |
 
1310
      static_cast<int32_t>(is_negative);
 
1311
  // Encode the individual bytes using the least significant bit of
 
1312
  // each byte to indicate whether or not more bytes follow.
 
1313
  do {
 
1314
    uint32_t next = bits >> 7;
 
1315
    contents_.Add(((bits << 1) & 0xFF) | (next != 0), zone);
 
1316
    bits = next;
 
1317
  } while (bits != 0);
 
1318
}
 
1319
 
 
1320
 
 
1321
int32_t TranslationIterator::Next() {
 
1322
  // Run through the bytes until we reach one with a least significant
 
1323
  // bit of zero (marks the end).
 
1324
  uint32_t bits = 0;
 
1325
  for (int i = 0; true; i += 7) {
 
1326
    ASSERT(HasNext());
 
1327
    uint8_t next = buffer_->get(index_++);
 
1328
    bits |= (next >> 1) << i;
 
1329
    if ((next & 1) == 0) break;
 
1330
  }
 
1331
  // The bits encode the sign in the least significant bit.
 
1332
  bool is_negative = (bits & 1) == 1;
 
1333
  int32_t result = bits >> 1;
 
1334
  return is_negative ? -result : result;
 
1335
}
 
1336
 
 
1337
 
 
1338
Handle<ByteArray> TranslationBuffer::CreateByteArray() {
 
1339
  int length = contents_.length();
 
1340
  Handle<ByteArray> result =
 
1341
      Isolate::Current()->factory()->NewByteArray(length, TENURED);
 
1342
  memcpy(result->GetDataStartAddress(), contents_.ToVector().start(), length);
 
1343
  return result;
 
1344
}
 
1345
 
 
1346
 
 
1347
void Translation::BeginConstructStubFrame(int literal_id, unsigned height) {
 
1348
  buffer_->Add(CONSTRUCT_STUB_FRAME, zone());
 
1349
  buffer_->Add(literal_id, zone());
 
1350
  buffer_->Add(height, zone());
 
1351
}
 
1352
 
 
1353
 
 
1354
void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) {
 
1355
  buffer_->Add(ARGUMENTS_ADAPTOR_FRAME, zone());
 
1356
  buffer_->Add(literal_id, zone());
 
1357
  buffer_->Add(height, zone());
 
1358
}
 
1359
 
 
1360
 
 
1361
void Translation::BeginJSFrame(int node_id, int literal_id, unsigned height) {
 
1362
  buffer_->Add(JS_FRAME, zone());
 
1363
  buffer_->Add(node_id, zone());
 
1364
  buffer_->Add(literal_id, zone());
 
1365
  buffer_->Add(height, zone());
 
1366
}
 
1367
 
 
1368
 
 
1369
void Translation::StoreRegister(Register reg) {
 
1370
  buffer_->Add(REGISTER, zone());
 
1371
  buffer_->Add(reg.code(), zone());
 
1372
}
 
1373
 
 
1374
 
 
1375
void Translation::StoreInt32Register(Register reg) {
 
1376
  buffer_->Add(INT32_REGISTER, zone());
 
1377
  buffer_->Add(reg.code(), zone());
 
1378
}
 
1379
 
 
1380
 
 
1381
void Translation::StoreDoubleRegister(DoubleRegister reg) {
 
1382
  buffer_->Add(DOUBLE_REGISTER, zone());
 
1383
  buffer_->Add(DoubleRegister::ToAllocationIndex(reg), zone());
 
1384
}
 
1385
 
 
1386
 
 
1387
void Translation::StoreStackSlot(int index) {
 
1388
  buffer_->Add(STACK_SLOT, zone());
 
1389
  buffer_->Add(index, zone());
 
1390
}
 
1391
 
 
1392
 
 
1393
void Translation::StoreInt32StackSlot(int index) {
 
1394
  buffer_->Add(INT32_STACK_SLOT, zone());
 
1395
  buffer_->Add(index, zone());
 
1396
}
 
1397
 
 
1398
 
 
1399
void Translation::StoreDoubleStackSlot(int index) {
 
1400
  buffer_->Add(DOUBLE_STACK_SLOT, zone());
 
1401
  buffer_->Add(index, zone());
 
1402
}
 
1403
 
 
1404
 
 
1405
void Translation::StoreLiteral(int literal_id) {
 
1406
  buffer_->Add(LITERAL, zone());
 
1407
  buffer_->Add(literal_id, zone());
 
1408
}
 
1409
 
 
1410
 
 
1411
void Translation::StoreArgumentsObject() {
 
1412
  buffer_->Add(ARGUMENTS_OBJECT, zone());
 
1413
}
 
1414
 
 
1415
 
 
1416
void Translation::MarkDuplicate() {
 
1417
  buffer_->Add(DUPLICATE, zone());
 
1418
}
 
1419
 
 
1420
 
 
1421
int Translation::NumberOfOperandsFor(Opcode opcode) {
 
1422
  switch (opcode) {
 
1423
    case ARGUMENTS_OBJECT:
 
1424
    case DUPLICATE:
 
1425
      return 0;
 
1426
    case REGISTER:
 
1427
    case INT32_REGISTER:
 
1428
    case DOUBLE_REGISTER:
 
1429
    case STACK_SLOT:
 
1430
    case INT32_STACK_SLOT:
 
1431
    case DOUBLE_STACK_SLOT:
 
1432
    case LITERAL:
 
1433
      return 1;
 
1434
    case BEGIN:
 
1435
    case ARGUMENTS_ADAPTOR_FRAME:
 
1436
    case CONSTRUCT_STUB_FRAME:
 
1437
      return 2;
 
1438
    case JS_FRAME:
 
1439
      return 3;
 
1440
  }
 
1441
  UNREACHABLE();
 
1442
  return -1;
 
1443
}
 
1444
 
 
1445
 
 
1446
#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
 
1447
 
 
1448
const char* Translation::StringFor(Opcode opcode) {
 
1449
  switch (opcode) {
 
1450
    case BEGIN:
 
1451
      return "BEGIN";
 
1452
    case JS_FRAME:
 
1453
      return "JS_FRAME";
 
1454
    case ARGUMENTS_ADAPTOR_FRAME:
 
1455
      return "ARGUMENTS_ADAPTOR_FRAME";
 
1456
    case CONSTRUCT_STUB_FRAME:
 
1457
      return "CONSTRUCT_STUB_FRAME";
 
1458
    case REGISTER:
 
1459
      return "REGISTER";
 
1460
    case INT32_REGISTER:
 
1461
      return "INT32_REGISTER";
 
1462
    case DOUBLE_REGISTER:
 
1463
      return "DOUBLE_REGISTER";
 
1464
    case STACK_SLOT:
 
1465
      return "STACK_SLOT";
 
1466
    case INT32_STACK_SLOT:
 
1467
      return "INT32_STACK_SLOT";
 
1468
    case DOUBLE_STACK_SLOT:
 
1469
      return "DOUBLE_STACK_SLOT";
 
1470
    case LITERAL:
 
1471
      return "LITERAL";
 
1472
    case ARGUMENTS_OBJECT:
 
1473
      return "ARGUMENTS_OBJECT";
 
1474
    case DUPLICATE:
 
1475
      return "DUPLICATE";
 
1476
  }
 
1477
  UNREACHABLE();
 
1478
  return "";
 
1479
}
 
1480
 
 
1481
#endif
 
1482
 
 
1483
 
 
1484
DeoptimizingCodeListNode::DeoptimizingCodeListNode(Code* code): next_(NULL) {
 
1485
  GlobalHandles* global_handles = Isolate::Current()->global_handles();
 
1486
  // Globalize the code object and make it weak.
 
1487
  code_ = Handle<Code>::cast(global_handles->Create(code));
 
1488
  global_handles->MakeWeak(reinterpret_cast<Object**>(code_.location()),
 
1489
                           this,
 
1490
                           Deoptimizer::HandleWeakDeoptimizedCode);
 
1491
}
 
1492
 
 
1493
 
 
1494
DeoptimizingCodeListNode::~DeoptimizingCodeListNode() {
 
1495
  GlobalHandles* global_handles = Isolate::Current()->global_handles();
 
1496
  global_handles->Destroy(reinterpret_cast<Object**>(code_.location()));
 
1497
}
 
1498
 
 
1499
 
 
1500
// We can't intermix stack decoding and allocations because
 
1501
// deoptimization infrastracture is not GC safe.
 
1502
// Thus we build a temporary structure in malloced space.
 
1503
SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator,
 
1504
                                            DeoptimizationInputData* data,
 
1505
                                            JavaScriptFrame* frame) {
 
1506
  Translation::Opcode opcode =
 
1507
      static_cast<Translation::Opcode>(iterator->Next());
 
1508
 
 
1509
  switch (opcode) {
 
1510
    case Translation::BEGIN:
 
1511
    case Translation::JS_FRAME:
 
1512
    case Translation::ARGUMENTS_ADAPTOR_FRAME:
 
1513
    case Translation::CONSTRUCT_STUB_FRAME:
 
1514
      // Peeled off before getting here.
 
1515
      break;
 
1516
 
 
1517
    case Translation::ARGUMENTS_OBJECT:
 
1518
      // This can be only emitted for local slots not for argument slots.
 
1519
      break;
 
1520
 
 
1521
    case Translation::REGISTER:
 
1522
    case Translation::INT32_REGISTER:
 
1523
    case Translation::DOUBLE_REGISTER:
 
1524
    case Translation::DUPLICATE:
 
1525
      // We are at safepoint which corresponds to call.  All registers are
 
1526
      // saved by caller so there would be no live registers at this
 
1527
      // point. Thus these translation commands should not be used.
 
1528
      break;
 
1529
 
 
1530
    case Translation::STACK_SLOT: {
 
1531
      int slot_index = iterator->Next();
 
1532
      Address slot_addr = SlotAddress(frame, slot_index);
 
1533
      return SlotRef(slot_addr, SlotRef::TAGGED);
 
1534
    }
 
1535
 
 
1536
    case Translation::INT32_STACK_SLOT: {
 
1537
      int slot_index = iterator->Next();
 
1538
      Address slot_addr = SlotAddress(frame, slot_index);
 
1539
      return SlotRef(slot_addr, SlotRef::INT32);
 
1540
    }
 
1541
 
 
1542
    case Translation::DOUBLE_STACK_SLOT: {
 
1543
      int slot_index = iterator->Next();
 
1544
      Address slot_addr = SlotAddress(frame, slot_index);
 
1545
      return SlotRef(slot_addr, SlotRef::DOUBLE);
 
1546
    }
 
1547
 
 
1548
    case Translation::LITERAL: {
 
1549
      int literal_index = iterator->Next();
 
1550
      return SlotRef(data->LiteralArray()->get(literal_index));
 
1551
    }
 
1552
  }
 
1553
 
 
1554
  UNREACHABLE();
 
1555
  return SlotRef();
 
1556
}
 
1557
 
 
1558
 
 
1559
void SlotRef::ComputeSlotsForArguments(Vector<SlotRef>* args_slots,
 
1560
                                       TranslationIterator* it,
 
1561
                                       DeoptimizationInputData* data,
 
1562
                                       JavaScriptFrame* frame) {
 
1563
  // Process the translation commands for the arguments.
 
1564
 
 
1565
  // Skip the translation command for the receiver.
 
1566
  it->Skip(Translation::NumberOfOperandsFor(
 
1567
      static_cast<Translation::Opcode>(it->Next())));
 
1568
 
 
1569
  // Compute slots for arguments.
 
1570
  for (int i = 0; i < args_slots->length(); ++i) {
 
1571
    (*args_slots)[i] = ComputeSlotForNextArgument(it, data, frame);
 
1572
  }
 
1573
}
 
1574
 
 
1575
 
 
1576
Vector<SlotRef> SlotRef::ComputeSlotMappingForArguments(
 
1577
    JavaScriptFrame* frame,
 
1578
    int inlined_jsframe_index,
 
1579
    int formal_parameter_count) {
 
1580
  AssertNoAllocation no_gc;
 
1581
  int deopt_index = AstNode::kNoNumber;
 
1582
  DeoptimizationInputData* data =
 
1583
      static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
 
1584
  TranslationIterator it(data->TranslationByteArray(),
 
1585
                         data->TranslationIndex(deopt_index)->value());
 
1586
  Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
 
1587
  ASSERT(opcode == Translation::BEGIN);
 
1588
  it.Next();  // Drop frame count.
 
1589
  int jsframe_count = it.Next();
 
1590
  USE(jsframe_count);
 
1591
  ASSERT(jsframe_count > inlined_jsframe_index);
 
1592
  int jsframes_to_skip = inlined_jsframe_index;
 
1593
  while (true) {
 
1594
    opcode = static_cast<Translation::Opcode>(it.Next());
 
1595
    if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) {
 
1596
      if (jsframes_to_skip == 0) {
 
1597
        ASSERT(Translation::NumberOfOperandsFor(opcode) == 2);
 
1598
 
 
1599
        it.Skip(1);  // literal id
 
1600
        int height = it.Next();
 
1601
 
 
1602
        // We reached the arguments adaptor frame corresponding to the
 
1603
        // inlined function in question.  Number of arguments is height - 1.
 
1604
        Vector<SlotRef> args_slots =
 
1605
            Vector<SlotRef>::New(height - 1);  // Minus receiver.
 
1606
        ComputeSlotsForArguments(&args_slots, &it, data, frame);
 
1607
        return args_slots;
 
1608
      }
 
1609
    } else if (opcode == Translation::JS_FRAME) {
 
1610
      if (jsframes_to_skip == 0) {
 
1611
        // Skip over operands to advance to the next opcode.
 
1612
        it.Skip(Translation::NumberOfOperandsFor(opcode));
 
1613
 
 
1614
        // We reached the frame corresponding to the inlined function
 
1615
        // in question.  Process the translation commands for the
 
1616
        // arguments.  Number of arguments is equal to the number of
 
1617
        // format parameter count.
 
1618
        Vector<SlotRef> args_slots =
 
1619
            Vector<SlotRef>::New(formal_parameter_count);
 
1620
        ComputeSlotsForArguments(&args_slots, &it, data, frame);
 
1621
        return args_slots;
 
1622
      }
 
1623
      jsframes_to_skip--;
 
1624
    }
 
1625
 
 
1626
    // Skip over operands to advance to the next opcode.
 
1627
    it.Skip(Translation::NumberOfOperandsFor(opcode));
 
1628
  }
 
1629
 
 
1630
  UNREACHABLE();
 
1631
  return Vector<SlotRef>();
 
1632
}
 
1633
 
 
1634
#ifdef ENABLE_DEBUGGER_SUPPORT
 
1635
 
 
1636
DeoptimizedFrameInfo::DeoptimizedFrameInfo(Deoptimizer* deoptimizer,
 
1637
                                           int frame_index,
 
1638
                                           bool has_arguments_adaptor,
 
1639
                                           bool has_construct_stub) {
 
1640
  FrameDescription* output_frame = deoptimizer->output_[frame_index];
 
1641
  function_ = output_frame->GetFunction();
 
1642
  has_construct_stub_ = has_construct_stub;
 
1643
  expression_count_ = output_frame->GetExpressionCount();
 
1644
  expression_stack_ = new Object*[expression_count_];
 
1645
  // Get the source position using the unoptimized code.
 
1646
  Address pc = reinterpret_cast<Address>(output_frame->GetPc());
 
1647
  Code* code = Code::cast(Isolate::Current()->heap()->FindCodeObject(pc));
 
1648
  source_position_ = code->SourcePosition(pc);
 
1649
 
 
1650
  for (int i = 0; i < expression_count_; i++) {
 
1651
    SetExpression(i, output_frame->GetExpression(i));
 
1652
  }
 
1653
 
 
1654
  if (has_arguments_adaptor) {
 
1655
    output_frame = deoptimizer->output_[frame_index - 1];
 
1656
    ASSERT(output_frame->GetFrameType() == StackFrame::ARGUMENTS_ADAPTOR);
 
1657
  }
 
1658
 
 
1659
  parameters_count_ = output_frame->ComputeParametersCount();
 
1660
  parameters_ = new Object*[parameters_count_];
 
1661
  for (int i = 0; i < parameters_count_; i++) {
 
1662
    SetParameter(i, output_frame->GetParameter(i));
 
1663
  }
 
1664
}
 
1665
 
 
1666
 
 
1667
DeoptimizedFrameInfo::~DeoptimizedFrameInfo() {
 
1668
  delete[] expression_stack_;
 
1669
  delete[] parameters_;
 
1670
}
 
1671
 
 
1672
 
 
1673
void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) {
 
1674
  v->VisitPointer(BitCast<Object**>(&function_));
 
1675
  v->VisitPointers(parameters_, parameters_ + parameters_count_);
 
1676
  v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
 
1677
}
 
1678
 
 
1679
#endif  // ENABLE_DEBUGGER_SUPPORT
 
1680
 
 
1681
} }  // namespace v8::internal