1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifndef V8_CRANKSHAFT_X87_LITHIUM_CODEGEN_X87_H_
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define V8_CRANKSHAFT_X87_LITHIUM_CODEGEN_X87_H_
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <map>
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ast/scopes.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/logging.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/lithium-codegen.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/x87/lithium-gap-resolver-x87.h"
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/x87/lithium-x87.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/deoptimizer.h"
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/safepoint-table.h"
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/utils.h"
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Forward declarations.
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass LDeferredCode;
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass LGapNode;
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SafepointGenerator;
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass LCodeGen: public LCodeGenBase {
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : LCodeGenBase(chunk, assembler, info),
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        jump_table_(4, info->zone()),
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        scope_(info->scope()),
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        deferred_(8, info->zone()),
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        dynamic_frame_alignment_(false),
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        support_aligned_spilled_doubles_(false),
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        frame_is_built_(false),
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        x87_stack_(assembler),
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        safepoints_(info->zone()),
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        resolver_(this),
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        expected_safepoint_kind_(Safepoint::kSimple) {
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PopulateDeoptimizationLiteralsWithInlinedFunctions();
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int LookupDestination(int block_id) const {
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return chunk()->LookupDestination(block_id);
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool IsNextEmittedBlock(int block_id) const {
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return LookupDestination(block_id) == GetNextEmittedBlock();
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool NeedsEagerFrame() const {
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return GetStackSlotCount() > 0 ||
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        info()->is_non_deferred_calling() ||
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        !info()->IsStub() ||
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        info()->requires_frame();
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool NeedsDeferredFrame() const {
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return !NeedsEagerFrame() && info()->is_deferred_calling();
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Support for converting LOperands to assembler types.
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand ToOperand(LOperand* op) const;
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register ToRegister(LOperand* op) const;
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register ToX87Register(LOperand* op) const;
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool IsInteger32(LConstantOperand* op) const;
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool IsSmi(LConstantOperand* op) const;
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Immediate ToImmediate(LOperand* op, const Representation& r) const {
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Immediate(ToRepresentation(LConstantOperand::cast(op), r));
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  double ToDouble(LConstantOperand* op) const;
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Support for non-sse2 (x87) floating point stack handling.
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // These functions maintain the mapping of physical stack registers to our
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // virtual registers between instructions.
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum X87OperandType { kX87DoubleOperand, kX87FloatOperand, kX87IntOperand };
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void X87Mov(X87Register reg, Operand src,
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      X87OperandType operand = kX87DoubleOperand);
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void X87Mov(Operand src, X87Register reg,
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      X87OperandType operand = kX87DoubleOperand);
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void X87Mov(X87Register reg, X87Register src,
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              X87OperandType operand = kX87DoubleOperand);
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void X87PrepareBinaryOp(
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      X87Register left, X87Register right, X87Register result);
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void X87LoadForUsage(X87Register reg);
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void X87LoadForUsage(X87Register reg1, X87Register reg2);
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void X87PrepareToWrite(X87Register reg) { x87_stack_.PrepareToWrite(reg); }
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void X87CommitWrite(X87Register reg) { x87_stack_.CommitWrite(reg); }
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void X87Fxch(X87Register reg, int other_slot = 0) {
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.Fxch(reg, other_slot);
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void X87Free(X87Register reg) {
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.Free(reg);
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool X87StackEmpty() {
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return x87_stack_.depth() == 0;
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> ToHandle(LConstantOperand* op) const;
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The operand denoting the second word (the one with a higher address) of
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // a double stack slot.
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand HighOperand(LOperand* op);
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Try to generate code for the entire chunk, but it may fail if the
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // chunk contains constructs we cannot handle. Returns true if the
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // code generation attempt succeeded.
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool GenerateCode();
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Finish the code by setting stack height, safepoint, and bailout
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // information on it.
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void FinishCode(Handle<Code> code);
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Deferred code support.
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoDeferredNumberTagD(LNumberTagD* instr);
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 };
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoDeferredNumberTagIU(LInstruction* instr,
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             LOperand* value,
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             LOperand* temp,
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             IntegerSignedness signedness);
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoDeferredTaggedToI(LTaggedToI* instr, Label* done);
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr);
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoDeferredStackCheck(LStackCheck* instr);
133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DoDeferredMaybeGrowElements(LMaybeGrowElements* instr);
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoDeferredAllocate(LAllocate* instr);
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register object,
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register index);
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Parallel move support.
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoParallelMove(LParallelMove* move);
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoGap(LGap* instr);
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emit frame translation commands for an environment.
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void WriteTranslation(LEnvironment* environment, Translation* translation);
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EnsureRelocSpaceForDeoptimization();
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Declare methods that deal with the individual node types.
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DECLARE_DO(type) void Do##type(L##type* node);
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DECLARE_DO
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LanguageMode language_mode() const { return info()->language_mode(); }
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Scope* scope() const { return scope_; }
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitClassOfTest(Label* if_true,
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       Label* if_false,
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       Handle<String> class_name,
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       Register input,
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       Register temporary,
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       Register temporary2);
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Code generation passes.  Returns true if code generation should
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // continue.
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GenerateBodyInstructionPre(LInstruction* instr) override;
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GenerateBodyInstructionPost(LInstruction* instr) override;
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool GeneratePrologue();
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool GenerateDeferredCode();
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool GenerateJumpTable();
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool GenerateSafepointTable();
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generates the custom OSR entrypoint and sets the osr_pc_offset.
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GenerateOsrPrologue();
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum SafepointMode {
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RECORD_SIMPLE_SAFEPOINT,
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallCode(Handle<Code> code,
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                RelocInfo::Mode mode,
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                LInstruction* instr);
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallCodeGeneric(Handle<Code> code,
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       RelocInfo::Mode mode,
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       LInstruction* instr,
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       SafepointMode safepoint_mode);
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallRuntime(const Runtime::Function* fun, int argc, LInstruction* instr,
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   SaveFPRegsMode save_doubles = kDontSaveFPRegs);
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallRuntime(Runtime::FunctionId id,
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   int argc,
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   LInstruction* instr) {
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const Runtime::Function* function = Runtime::FunctionForId(id);
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallRuntime(function, argc, instr);
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CallRuntime(Runtime::FunctionId id, LInstruction* instr) {
209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const Runtime::Function* function = Runtime::FunctionForId(id);
210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallRuntime(function, function->nargs, instr);
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallRuntimeFromDeferred(Runtime::FunctionId id,
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               int argc,
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               LInstruction* instr,
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               LOperand* context);
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadContextFromDeferred(LOperand* context);
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generate a direct call to a known function.  Expects the function
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to be in edi.
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallKnownFunction(Handle<JSFunction> function,
223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         int formal_parameter_count, int arity,
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         LInstruction* instr);
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordSafepointWithLazyDeopt(LInstruction* instr,
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    SafepointMode safepoint_mode);
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            Safepoint::DeoptMode mode);
231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DeoptimizeIf(Condition cc, LInstruction* instr,
232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    Deoptimizer::DeoptReason deopt_reason,
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    Deoptimizer::BailoutType bailout_type);
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DeoptimizeIf(Condition cc, LInstruction* instr,
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    Deoptimizer::DeoptReason deopt_reason);
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool DeoptEveryNTimes() {
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return FLAG_deopt_every_n_times != 0 && !info()->IsStub();
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AddToTranslation(LEnvironment* environment,
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Translation* translation,
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        LOperand* op,
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        bool is_tagged,
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        bool is_uint32,
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        int* object_index_pointer,
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        int* dematerialized_index_pointer);
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register ToRegister(int index) const;
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register ToX87Register(int index) const;
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t ToInteger32(LConstantOperand* op) const;
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference ToExternalReference(LConstantOperand* op) const;
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand BuildFastArrayOperand(LOperand* elements_pointer,
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                LOperand* key,
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                Representation key_representation,
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                ElementsKind elements_kind,
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                uint32_t base_offset);
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand BuildSeqStringOperand(Register string,
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                LOperand* index,
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                String::Encoding encoding);
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitIntegerMathAbs(LMathAbs* instr);
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Support for recording safepoint and position information.
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordSafepoint(LPointerMap* pointers,
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       Safepoint::Kind kind,
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       int arguments,
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       Safepoint::DeoptMode mode);
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordSafepoint(Safepoint::DeoptMode mode);
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordSafepointWithRegisters(LPointerMap* pointers,
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    int arguments,
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    Safepoint::DeoptMode mode);
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void RecordAndWritePosition(int position) override;
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Condition TokenToCondition(Token::Value op, bool is_unsigned);
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitGoto(int block);
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // EmitBranch expects to be the last instruction of a block.
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<class InstrType>
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitBranch(InstrType instr, Condition cc);
286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <class InstrType>
287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EmitTrueBranch(InstrType instr, Condition cc);
288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <class InstrType>
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitFalseBranch(InstrType instr, Condition cc);
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input,
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register temp, X87Register res_reg,
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              NumberUntagDMode mode);
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emits optimized code for typeof x == "y".  Modifies input register.
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns the condition on which a final split to
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // true and false label should be made, to optimize fallthrough.
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input);
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emits optimized code for %_IsString(x).  Preserves input register.
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns the condition on which a final split to
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // true and false label should be made, to optimize fallthrough.
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition EmitIsString(Register input,
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register temp1,
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label* is_not_string,
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         SmiCheck check_needed);
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emits optimized code to deep-copy the contents of statically known
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object graphs (e.g. object literal boilerplate).
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitDeepCopy(Handle<JSObject> object,
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    Register result,
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    Register source,
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    int* offset,
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    AllocationSiteMode mode);
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EnsureSpaceForLazyDeopt(int space_needed) override;
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoLoadKeyedExternalArray(LLoadKeyed* instr);
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr);
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoLoadKeyedFixedArray(LLoadKeyed* instr);
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoStoreKeyedExternalArray(LStoreKeyed* instr);
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoStoreKeyedFixedArray(LStoreKeyed* instr);
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template <class T>
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitVectorLoadICRegisters(T* instr);
325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <class T>
326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EmitVectorStoreICRegisters(T* instr);
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitReturn(LReturn* instr, bool dynamic_frame_alignment);
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emits code for pushing either a tagged constant, a (non-double)
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // register, or a stack slot operand.
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitPushTaggedOperand(LOperand* operand);
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void X87Fld(Operand src, X87OperandType opts);
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitFlushX87ForDeopt();
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void FlushX87StackIfNecessary(LInstruction* instr) {
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.FlushIfNecessary(instr, this);
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class LGapResolver;
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _MSC_VER
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // On windows, you may not access the stack more than one page below
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the most recently mapped page. To make the allocated area randomly
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // accessible, we write an arbitrary value to each page in range
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // esp + offset - page_size .. esp in turn.
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MakeSureStackPagesMapped(int offset);
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Deoptimizer::JumpTableEntry> jump_table_;
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Scope* const scope_;
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<LDeferredCode*> deferred_;
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool dynamic_frame_alignment_;
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool support_aligned_spilled_doubles_;
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool frame_is_built_;
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  class X87Stack : public ZoneObject {
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    explicit X87Stack(MacroAssembler* masm)
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : stack_depth_(0), is_mutable_(true), masm_(masm) { }
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    explicit X87Stack(const X87Stack& other)
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : stack_depth_(other.stack_depth_), is_mutable_(false), masm_(masm()) {
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (int i = 0; i < stack_depth_; i++) {
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        stack_[i] = other.stack_[i];
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool operator==(const X87Stack& other) const {
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (stack_depth_ != other.stack_depth_) return false;
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (int i = 0; i < stack_depth_; i++) {
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (!stack_[i].is(other.stack_[i])) return false;
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return true;
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Stack& operator=(const X87Stack& other) {
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stack_depth_ = other.stack_depth_;
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (int i = 0; i < stack_depth_; i++) {
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        stack_[i] = other.stack_[i];
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return *this;
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool Contains(X87Register reg);
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void Fxch(X87Register reg, int other_slot = 0);
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void Free(X87Register reg);
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void PrepareToWrite(X87Register reg);
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void CommitWrite(X87Register reg);
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void FlushIfNecessary(LInstruction* instr, LCodeGen* cgen);
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void LeavingBlock(int current_block_id, LGoto* goto_instr, LCodeGen* cgen);
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int depth() const { return stack_depth_; }
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int GetLayout();
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int st(X87Register reg) { return st2idx(ArrayIndex(reg)); }
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void pop() {
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(is_mutable_);
393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      USE(is_mutable_);
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stack_depth_--;
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void push(X87Register reg) {
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(is_mutable_);
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(stack_depth_ < X87Register::kMaxNumAllocatableRegisters);
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stack_[stack_depth_] = reg;
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stack_depth_++;
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm() const { return masm_; }
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Isolate* isolate() const { return masm_->isolate(); }
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int ArrayIndex(X87Register reg);
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int st2idx(int pos);
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Register stack_[X87Register::kMaxNumAllocatableRegisters];
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int stack_depth_;
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool is_mutable_;
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm_;
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Stack x87_stack_;
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // block_id -> X87Stack*;
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef std::map<int, X87Stack*> X87StackMap;
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87StackMap x87_stack_map_;
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Builder that keeps track of safepoints in the code. The table
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // itself is emitted at the end of the generated code.
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SafepointTableBuilder safepoints_;
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compiler from a set of parallel moves to a sequential list of moves.
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LGapResolver resolver_;
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Safepoint::Kind expected_safepoint_kind_;
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class PushSafepointRegistersScope final BASE_EMBEDDED {
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    explicit PushSafepointRegistersScope(LCodeGen* codegen)
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : codegen_(codegen) {
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen_->masm_->PushSafepointRegisters();
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters;
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(codegen_->info()->is_calling());
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ~PushSafepointRegistersScope() {
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters);
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen_->masm_->PopSafepointRegisters();
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LCodeGen* codegen_;
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class LDeferredCode;
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class LEnvironment;
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class SafepointGenerator;
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class X87Stack;
453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(LCodeGen);
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass LDeferredCode : public ZoneObject {
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit LDeferredCode(LCodeGen* codegen, const LCodeGen::X87Stack& x87_stack)
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : codegen_(codegen),
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        external_exit_(NULL),
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instruction_index_(codegen->current_instruction_),
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        x87_stack_(x87_stack) {
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    codegen->AddDeferredCode(this);
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~LDeferredCode() {}
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void Generate() = 0;
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual LInstruction* instr() = 0;
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetExit(Label* exit) { external_exit_ = exit; }
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* entry() { return &entry_; }
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* done() { return codegen_->NeedsDeferredFrame() ? &done_ : exit(); }
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int instruction_index() const { return instruction_index_; }
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const LCodeGen::X87Stack& x87_stack() const { return x87_stack_; }
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected:
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LCodeGen* codegen() const { return codegen_; }
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MacroAssembler* masm() const { return codegen_->masm(); }
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LCodeGen* codegen_;
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label entry_;
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label exit_;
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* external_exit_;
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done_;
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int instruction_index_;
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LCodeGen::X87Stack x87_stack_;
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif  // V8_CRANKSHAFT_X87_LITHIUM_CODEGEN_X87_H_
496