1864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
2864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be
3864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// found in the LICENSE file.
4864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifndef V8_X87_LITHIUM_CODEGEN_X87_H_
6864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#define V8_X87_LITHIUM_CODEGEN_X87_H_
7864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org#include <map>
9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/x87/lithium-x87.h"
10864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
115de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/logging.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/deoptimizer.h"
13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/lithium-codegen.h"
14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/safepoint-table.h"
15196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/scopes.h"
16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/utils.h"
174b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/x87/lithium-gap-resolver-x87.h"
18864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
19864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace v8 {
20864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace internal {
21864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
22864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Forward declarations.
23864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgclass LDeferredCode;
24864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgclass LGapNode;
25864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgclass SafepointGenerator;
26864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
27864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgclass LCodeGen: public LCodeGenBase {
28864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org public:
29864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
30864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      : LCodeGenBase(chunk, assembler, info),
31864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        deoptimizations_(4, info->zone()),
32864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        jump_table_(4, info->zone()),
33864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        deoptimization_literals_(8, info->zone()),
34864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        inlined_function_count_(0),
35864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        scope_(info->scope()),
36864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        translations_(info->zone()),
37864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        deferred_(8, info->zone()),
38864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        dynamic_frame_alignment_(false),
39864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        support_aligned_spilled_doubles_(false),
40864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        osr_pc_offset_(-1),
41864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        frame_is_built_(false),
42864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        x87_stack_(assembler),
43864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        safepoints_(info->zone()),
44864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        resolver_(this),
45864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        expected_safepoint_kind_(Safepoint::kSimple) {
46864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PopulateDeoptimizationLiteralsWithInlinedFunctions();
47864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
48864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
49864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int LookupDestination(int block_id) const {
50864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return chunk()->LookupDestination(block_id);
51864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
52864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
53864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool IsNextEmittedBlock(int block_id) const {
54864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return LookupDestination(block_id) == GetNextEmittedBlock();
55864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
56864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
57864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool NeedsEagerFrame() const {
58864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return GetStackSlotCount() > 0 ||
59864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        info()->is_non_deferred_calling() ||
60864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        !info()->IsStub() ||
61864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        info()->requires_frame();
62864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
63864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool NeedsDeferredFrame() const {
64864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return !NeedsEagerFrame() && info()->is_deferred_calling();
65864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
66864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
67864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Support for converting LOperands to assembler types.
68864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand ToOperand(LOperand* op) const;
69864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register ToRegister(LOperand* op) const;
70864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Register ToX87Register(LOperand* op) const;
71864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
72864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool IsInteger32(LConstantOperand* op) const;
73864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool IsSmi(LConstantOperand* op) const;
74864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Immediate ToImmediate(LOperand* op, const Representation& r) const {
75864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return Immediate(ToRepresentation(LConstantOperand::cast(op), r));
76864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
77864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  double ToDouble(LConstantOperand* op) const;
78864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
79864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Support for non-sse2 (x87) floating point stack handling.
80864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // These functions maintain the mapping of physical stack registers to our
81864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // virtual registers between instructions.
82864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  enum X87OperandType { kX87DoubleOperand, kX87FloatOperand, kX87IntOperand };
83864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
84864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void X87Mov(X87Register reg, Operand src,
85864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      X87OperandType operand = kX87DoubleOperand);
86864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void X87Mov(Operand src, X87Register reg,
87864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      X87OperandType operand = kX87DoubleOperand);
8806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  void X87Mov(X87Register reg, X87Register src,
8906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org              X87OperandType operand = kX87DoubleOperand);
90864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
91864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void X87PrepareBinaryOp(
92864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      X87Register left, X87Register right, X87Register result);
93864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
94864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void X87LoadForUsage(X87Register reg);
95864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void X87LoadForUsage(X87Register reg1, X87Register reg2);
96864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void X87PrepareToWrite(X87Register reg) { x87_stack_.PrepareToWrite(reg); }
97864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void X87CommitWrite(X87Register reg) { x87_stack_.CommitWrite(reg); }
98864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
99864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void X87Fxch(X87Register reg, int other_slot = 0) {
100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    x87_stack_.Fxch(reg, other_slot);
101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void X87Free(X87Register reg) {
103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    x87_stack_.Free(reg);
104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool X87StackEmpty() {
108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return x87_stack_.depth() == 0;
109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Object> ToHandle(LConstantOperand* op) const;
112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The operand denoting the second word (the one with a higher address) of
114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // a double stack slot.
115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand HighOperand(LOperand* op);
116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Try to generate code for the entire chunk, but it may fail if the
118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // chunk contains constructs we cannot handle. Returns true if the
119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // code generation attempt succeeded.
120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool GenerateCode();
121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Finish the code by setting stack height, safepoint, and bailout
123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // information on it.
124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void FinishCode(Handle<Code> code);
125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Deferred code support.
127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoDeferredNumberTagD(LNumberTagD* instr);
128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 };
130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoDeferredNumberTagIU(LInstruction* instr,
131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                             LOperand* value,
132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                             LOperand* temp,
133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                             IntegerSignedness signedness);
134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoDeferredTaggedToI(LTaggedToI* instr, Label* done);
136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr);
137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoDeferredStackCheck(LStackCheck* instr);
138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoDeferredAllocate(LAllocate* instr);
141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                       Label* map_check);
143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                   Register object,
146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                   Register index);
147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Parallel move support.
149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoParallelMove(LParallelMove* move);
150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoGap(LGap* instr);
151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Emit frame translation commands for an environment.
153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void WriteTranslation(LEnvironment* environment, Translation* translation);
154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EnsureRelocSpaceForDeoptimization();
156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Declare methods that deal with the individual node types.
158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#define DECLARE_DO(type) void Do##type(L##type* node);
159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#undef DECLARE_DO
161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org private:
163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  StrictMode strict_mode() const { return info()->strict_mode(); }
164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Scope* scope() const { return scope_; }
166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitClassOfTest(Label* if_true,
168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       Label* if_false,
169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       Handle<String> class_name,
170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       Register input,
171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       Register temporary,
172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       Register temporary2);
173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Code generation passes.  Returns true if code generation should
179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // continue.
180ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  void GenerateBodyInstructionPre(LInstruction* instr) OVERRIDE;
181ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  void GenerateBodyInstructionPost(LInstruction* instr) OVERRIDE;
182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool GeneratePrologue();
183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool GenerateDeferredCode();
184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool GenerateJumpTable();
185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool GenerateSafepointTable();
186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Generates the custom OSR entrypoint and sets the osr_pc_offset.
188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void GenerateOsrPrologue();
189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  enum SafepointMode {
191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    RECORD_SIMPLE_SAFEPOINT,
192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS
193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void CallCode(Handle<Code> code,
196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                RelocInfo::Mode mode,
197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                LInstruction* instr);
198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void CallCodeGeneric(Handle<Code> code,
200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       RelocInfo::Mode mode,
201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       LInstruction* instr,
202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       SafepointMode safepoint_mode);
203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
20406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  void CallRuntime(const Runtime::Function* fun, int argc, LInstruction* instr,
20506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                   SaveFPRegsMode save_doubles = kDontSaveFPRegs);
206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void CallRuntime(Runtime::FunctionId id,
208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   int argc,
209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   LInstruction* instr) {
210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    const Runtime::Function* function = Runtime::FunctionForId(id);
211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallRuntime(function, argc, instr);
212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void CallRuntimeFromDeferred(Runtime::FunctionId id,
215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               int argc,
216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               LInstruction* instr,
217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               LOperand* context);
218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void LoadContextFromDeferred(LOperand* context);
220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  enum EDIState {
222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EDI_UNINITIALIZED,
223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EDI_CONTAINS_TARGET
224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Generate a direct call to a known function.  Expects the function
227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // to be in edi.
228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void CallKnownFunction(Handle<JSFunction> function,
229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         int formal_parameter_count,
230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         int arity,
231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         LInstruction* instr,
232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         EDIState edi_state);
233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void RecordSafepointWithLazyDeopt(LInstruction* instr,
235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    SafepointMode safepoint_mode);
236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                            Safepoint::DeoptMode mode);
23906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  void DeoptimizeIf(Condition cc, LInstruction* instr, const char* detail,
240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                    Deoptimizer::BailoutType bailout_type);
241b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  void DeoptimizeIf(Condition cc, LInstruction* instr, const char* detail);
242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool DeoptEveryNTimes() {
244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return FLAG_deopt_every_n_times != 0 && !info()->IsStub();
245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void AddToTranslation(LEnvironment* environment,
248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        Translation* translation,
249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        LOperand* op,
250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        bool is_tagged,
251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        bool is_uint32,
252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        int* object_index_pointer,
253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        int* dematerialized_index_pointer);
254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void PopulateDeoptimizationData(Handle<Code> code);
255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int DefineDeoptimizationLiteral(Handle<Object> literal);
256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void PopulateDeoptimizationLiteralsWithInlinedFunctions();
258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register ToRegister(int index) const;
260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Register ToX87Register(int index) const;
261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t ToInteger32(LConstantOperand* op) const;
263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference ToExternalReference(LConstantOperand* op) const;
264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand BuildFastArrayOperand(LOperand* elements_pointer,
266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                LOperand* key,
267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                Representation key_representation,
268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                ElementsKind elements_kind,
269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                uint32_t base_offset);
270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand BuildSeqStringOperand(Register string,
272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                LOperand* index,
273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                String::Encoding encoding);
274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitIntegerMathAbs(LMathAbs* instr);
276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Support for recording safepoint and position information.
278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void RecordSafepoint(LPointerMap* pointers,
279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       Safepoint::Kind kind,
280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       int arguments,
281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       Safepoint::DeoptMode mode);
282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void RecordSafepoint(Safepoint::DeoptMode mode);
284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void RecordSafepointWithRegisters(LPointerMap* pointers,
285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    int arguments,
286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    Safepoint::DeoptMode mode);
287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
288ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  void RecordAndWritePosition(int position) OVERRIDE;
289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  static Condition TokenToCondition(Token::Value op, bool is_unsigned);
291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitGoto(int block);
292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // EmitBranch expects to be the last instruction of a block.
294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  template<class InstrType>
295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitBranch(InstrType instr, Condition cc);
296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  template<class InstrType>
297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitFalseBranch(InstrType instr, Condition cc);
298a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  void EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input,
299a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org                              Register temp, X87Register res_reg,
300a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org                              NumberUntagDMode mode);
301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Emits optimized code for typeof x == "y".  Modifies input register.
303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Returns the condition on which a final split to
304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // true and false label should be made, to optimize fallthrough.
305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input);
306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Emits optimized code for %_IsObject(x).  Preserves input register.
308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Returns the condition on which a final split to
309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // true and false label should be made, to optimize fallthrough.
310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition EmitIsObject(Register input,
311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         Register temp1,
312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         Label* is_not_object,
313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         Label* is_object);
314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Emits optimized code for %_IsString(x).  Preserves input register.
316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Returns the condition on which a final split to
317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // true and false label should be made, to optimize fallthrough.
318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition EmitIsString(Register input,
319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         Register temp1,
320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         Label* is_not_string,
321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         SmiCheck check_needed);
322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Emits optimized code for %_IsConstructCall().
324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Caller should branch on equal condition.
325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitIsConstructCall(Register temp);
326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Emits optimized code to deep-copy the contents of statically known
328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // object graphs (e.g. object literal boilerplate).
329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitDeepCopy(Handle<JSObject> object,
330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                    Register result,
331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                    Register source,
332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                    int* offset,
333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                    AllocationSiteMode mode);
334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
335ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  void EnsureSpaceForLazyDeopt(int space_needed) OVERRIDE;
336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoLoadKeyedExternalArray(LLoadKeyed* instr);
337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr);
338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoLoadKeyedFixedArray(LLoadKeyed* instr);
339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoStoreKeyedExternalArray(LStoreKeyed* instr);
340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void DoStoreKeyedFixedArray(LStoreKeyed* instr);
342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
343fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  template <class T>
344fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  void EmitVectorLoadICRegisters(T* instr);
345fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org
346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitReturn(LReturn* instr, bool dynamic_frame_alignment);
347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Emits code for pushing either a tagged constant, a (non-double)
349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // register, or a stack slot operand.
350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitPushTaggedOperand(LOperand* operand);
351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void X87Fld(Operand src, X87OperandType opts);
353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void EmitFlushX87ForDeopt();
355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void FlushX87StackIfNecessary(LInstruction* instr) {
356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    x87_stack_.FlushIfNecessary(instr, this);
357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  friend class LGapResolver;
359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef _MSC_VER
361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // On windows, you may not access the stack more than one page below
362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the most recently mapped page. To make the allocated area randomly
363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // accessible, we write an arbitrary value to each page in range
364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // esp + offset - page_size .. esp in turn.
365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void MakeSureStackPagesMapped(int offset);
366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<LEnvironment*> deoptimizations_;
369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Deoptimizer::JumpTableEntry> jump_table_;
370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<Handle<Object> > deoptimization_literals_;
371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int inlined_function_count_;
372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Scope* const scope_;
373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  TranslationBuffer translations_;
374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ZoneList<LDeferredCode*> deferred_;
375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool dynamic_frame_alignment_;
376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool support_aligned_spilled_doubles_;
377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int osr_pc_offset_;
378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool frame_is_built_;
379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
38006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  class X87Stack : public ZoneObject {
381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    explicit X87Stack(MacroAssembler* masm)
383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : stack_depth_(0), is_mutable_(true), masm_(masm) { }
384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    explicit X87Stack(const X87Stack& other)
385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : stack_depth_(other.stack_depth_), is_mutable_(false), masm_(masm()) {
386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      for (int i = 0; i < stack_depth_; i++) {
387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        stack_[i] = other.stack_[i];
388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bool operator==(const X87Stack& other) const {
391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (stack_depth_ != other.stack_depth_) return false;
392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      for (int i = 0; i < stack_depth_; i++) {
393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (!stack_[i].is(other.stack_[i])) return false;
394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      return true;
396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
39706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87Stack& operator=(const X87Stack& other) {
39806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      stack_depth_ = other.stack_depth_;
39906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      for (int i = 0; i < stack_depth_; i++) {
40006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org        stack_[i] = other.stack_[i];
40106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      }
40206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      return *this;
40306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    }
404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bool Contains(X87Register reg);
405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    void Fxch(X87Register reg, int other_slot = 0);
406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    void Free(X87Register reg);
407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    void PrepareToWrite(X87Register reg);
408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    void CommitWrite(X87Register reg);
409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    void FlushIfNecessary(LInstruction* instr, LCodeGen* cgen);
41006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    void LeavingBlock(int current_block_id, LGoto* goto_instr, LCodeGen* cgen);
411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int depth() const { return stack_depth_; }
41206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    int GetLayout();
41306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    int st(X87Register reg) { return st2idx(ArrayIndex(reg)); }
414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    void pop() {
415e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(is_mutable_);
416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      stack_depth_--;
417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    void push(X87Register reg) {
419e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(is_mutable_);
420e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(stack_depth_ < X87Register::kMaxNumAllocatableRegisters);
421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      stack_[stack_depth_] = reg;
422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      stack_depth_++;
423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    MacroAssembler* masm() const { return masm_; }
426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Isolate* isolate() const { return masm_->isolate(); }
427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int ArrayIndex(X87Register reg);
430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int st2idx(int pos);
431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Register stack_[X87Register::kMaxNumAllocatableRegisters];
433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int stack_depth_;
434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bool is_mutable_;
435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    MacroAssembler* masm_;
436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Stack x87_stack_;
43806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // block_id -> X87Stack*;
43906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  typedef std::map<int, X87Stack*> X87StackMap;
44006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87StackMap x87_stack_map_;
441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Builder that keeps track of safepoints in the code. The table
443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // itself is emitted at the end of the generated code.
444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SafepointTableBuilder safepoints_;
445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Compiler from a set of parallel moves to a sequential list of moves.
447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LGapResolver resolver_;
448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Safepoint::Kind expected_safepoint_kind_;
450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
451ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class PushSafepointRegistersScope FINAL  BASE_EMBEDDED {
452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    explicit PushSafepointRegistersScope(LCodeGen* codegen)
454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : codegen_(codegen) {
455e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen_->masm_->PushSafepointRegisters();
457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters;
458e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(codegen_->info()->is_calling());
459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ~PushSafepointRegistersScope() {
462e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters);
463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen_->masm_->PopSafepointRegisters();
464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LCodeGen* codegen_;
469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  friend class LDeferredCode;
472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  friend class LEnvironment;
473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  friend class SafepointGenerator;
47406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  friend class X87Stack;
475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DISALLOW_COPY_AND_ASSIGN(LCodeGen);
476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org};
477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgclass LDeferredCode : public ZoneObject {
480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org public:
481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  explicit LDeferredCode(LCodeGen* codegen, const LCodeGen::X87Stack& x87_stack)
482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      : codegen_(codegen),
483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        external_exit_(NULL),
484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        instruction_index_(codegen->current_instruction_),
485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        x87_stack_(x87_stack) {
486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    codegen->AddDeferredCode(this);
487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  virtual ~LDeferredCode() {}
490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  virtual void Generate() = 0;
491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  virtual LInstruction* instr() = 0;
492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  void SetExit(Label* exit) { external_exit_ = exit; }
494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* entry() { return &entry_; }
495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* done() { return codegen_->NeedsDeferredFrame() ? &done_ : exit(); }
497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int instruction_index() const { return instruction_index_; }
498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const LCodeGen::X87Stack& x87_stack() const { return x87_stack_; }
499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org protected:
501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LCodeGen* codegen() const { return codegen_; }
502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  MacroAssembler* masm() const { return codegen_->masm(); }
503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org private:
505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LCodeGen* codegen_;
506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label entry_;
507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label exit_;
508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* external_exit_;
509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done_;
510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int instruction_index_;
511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LCodeGen::X87Stack x87_stack_;
512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org};
513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} }  // namespace v8::internal
515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif  // V8_X87_LITHIUM_CODEGEN_X87_H_
517