1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved.
2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be
3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file.
4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifndef V8_CRANKSHAFT_PPC_LITHIUM_CODEGEN_PPC_H_
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define V8_CRANKSHAFT_PPC_LITHIUM_CODEGEN_PPC_H_
7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ast/scopes.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/lithium-codegen.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/ppc/lithium-gap-resolver-ppc.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/ppc/lithium-ppc.h"
12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/deoptimizer.h"
13958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/safepoint-table.h"
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/utils.h"
15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 {
17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal {
18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Forward declarations.
20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass LDeferredCode;
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass SafepointGenerator;
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass LCodeGen : public LCodeGenBase {
24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      : LCodeGenBase(chunk, assembler, info),
27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        jump_table_(4, info->zone()),
28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        scope_(info->scope()),
29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        deferred_(8, info->zone()),
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        frame_is_built_(false),
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        safepoints_(info->zone()),
32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        resolver_(this),
33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        expected_safepoint_kind_(Safepoint::kSimple) {
34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PopulateDeoptimizationLiteralsWithInlinedFunctions();
35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int LookupDestination(int block_id) const {
39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return chunk()->LookupDestination(block_id);
40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool IsNextEmittedBlock(int block_id) const {
43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return LookupDestination(block_id) == GetNextEmittedBlock();
44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool NeedsEagerFrame() const {
47109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return HasAllocatedStackSlots() || info()->is_non_deferred_calling() ||
48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           !info()->IsStub() || info()->requires_frame();
49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool NeedsDeferredFrame() const {
51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return !NeedsEagerFrame() && info()->is_deferred_calling();
52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  LinkRegisterStatus GetLinkRegisterState() const {
55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return frame_is_built_ ? kLRHasBeenSaved : kLRHasNotBeenSaved;
56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Support for converting LOperands to assembler types.
59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // LOperand must be a register.
60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register ToRegister(LOperand* op) const;
61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // LOperand is loaded into scratch, unless already a register.
63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register EmitLoadRegister(LOperand* op, Register scratch);
64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
65958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // LConstantOperand must be an Integer32 or Smi
66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EmitLoadIntegerConstant(LConstantOperand* const_op, Register dst);
67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // LOperand must be a double register.
69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DoubleRegister ToDoubleRegister(LOperand* op) const;
70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  intptr_t ToRepresentation(LConstantOperand* op,
72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                            const Representation& r) const;
73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int32_t ToInteger32(LConstantOperand* op) const;
74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Smi* ToSmi(LConstantOperand* op) const;
75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  double ToDouble(LConstantOperand* op) const;
76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Operand ToOperand(LOperand* op);
77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MemOperand ToMemOperand(LOperand* op) const;
78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Returns a MemOperand pointing to the high word of a DoubleStackSlot.
79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MemOperand ToHighMemOperand(LOperand* op) const;
80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool IsInteger32(LConstantOperand* op) const;
82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool IsSmi(LConstantOperand* op) const;
83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Object> ToHandle(LConstantOperand* op) const;
84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Try to generate code for the entire chunk, but it may fail if the
86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // chunk contains constructs we cannot handle. Returns true if the
87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // code generation attempt succeeded.
88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool GenerateCode();
89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Finish the code by setting stack height, safepoint, and bailout
91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // information on it.
92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void FinishCode(Handle<Code> code);
93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Deferred code support.
95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoDeferredNumberTagD(LNumberTagD* instr);
96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 };
98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoDeferredNumberTagIU(LInstruction* instr, LOperand* value,
99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                             LOperand* temp1, LOperand* temp2,
100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                             IntegerSignedness signedness);
101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoDeferredTaggedToI(LTaggedToI* instr);
103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr);
104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoDeferredStackCheck(LStackCheck* instr);
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DoDeferredMaybeGrowElements(LMaybeGrowElements* instr);
106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoDeferredAllocate(LAllocate* instr);
109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, Register result,
111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                   Register object, Register index);
112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Parallel move support.
114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoParallelMove(LParallelMove* move);
115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoGap(LGap* instr);
116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MemOperand PrepareKeyedOperand(Register key, Register base,
118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                 bool key_is_constant, bool key_is_tagged,
119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                 int constant_key, int element_size_shift,
120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                 int base_offset);
121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Emit frame translation commands for an environment.
123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void WriteTranslation(LEnvironment* environment, Translation* translation);
124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Declare methods that deal with the individual node types.
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define DECLARE_DO(type) void Do##type(L##type* node);
127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef DECLARE_DO
129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Scope* scope() const { return scope_; }
132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch0() { return kLithiumScratch; }
134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DoubleRegister double_scratch0() { return kScratchDoubleReg; }
135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  LInstruction* GetNextInstruction();
137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EmitClassOfTest(Label* if_true, Label* if_false,
139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       Handle<String> class_name, Register input,
140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       Register temporary, Register temporary2);
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
142109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bool HasAllocatedStackSlots() const {
143109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return chunk()->HasAllocatedStackSlots();
144109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
145109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int GetStackSlotCount() const { return chunk()->GetSpillSlotCount(); }
146109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int GetTotalFrameSlotCount() const {
147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return chunk()->GetTotalFrameSlotCount();
148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void SaveCallerDoubles();
153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void RestoreCallerDoubles();
154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Code generation passes.  Returns true if code generation should
156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // continue.
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GenerateBodyInstructionPre(LInstruction* instr) override;
158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool GeneratePrologue();
159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool GenerateDeferredCode();
160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool GenerateJumpTable();
161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool GenerateSafepointTable();
162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Generates the custom OSR entrypoint and sets the osr_pc_offset.
164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void GenerateOsrPrologue();
165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  enum SafepointMode {
167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    RECORD_SIMPLE_SAFEPOINT,
168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS
169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  };
170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void CallCode(Handle<Code> code, RelocInfo::Mode mode, LInstruction* instr);
172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void CallCodeGeneric(Handle<Code> code, RelocInfo::Mode mode,
174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       LInstruction* instr, SafepointMode safepoint_mode);
175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void CallRuntime(const Runtime::Function* function, int num_arguments,
177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   LInstruction* instr,
178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   SaveFPRegsMode save_doubles = kDontSaveFPRegs);
179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void CallRuntime(Runtime::FunctionId id, int num_arguments,
181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   LInstruction* instr) {
182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    const Runtime::Function* function = Runtime::FunctionForId(id);
183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    CallRuntime(function, num_arguments, instr);
184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CallRuntime(Runtime::FunctionId id, LInstruction* instr) {
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const Runtime::Function* function = Runtime::FunctionForId(id);
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallRuntime(function, function->nargs, instr);
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void LoadContextFromDeferred(LOperand* context);
192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void CallRuntimeFromDeferred(Runtime::FunctionId id, int argc,
193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                               LInstruction* instr, LOperand* context);
194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PrepareForTailCall(const ParameterCount& actual, Register scratch1,
1963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                          Register scratch2, Register scratch3);
1973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Generate a direct call to a known function.  Expects the function
199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // to be in r4.
200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void CallKnownFunction(Handle<JSFunction> function,
201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         int formal_parameter_count, int arity,
2023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                         bool is_tail_call, LInstruction* instr);
203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void RecordSafepointWithLazyDeopt(LInstruction* instr,
205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    SafepointMode safepoint_mode);
206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                            Safepoint::DeoptMode mode);
209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DeoptimizeIf(Condition condition, LInstruction* instr,
210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    DeoptimizeReason deopt_reason,
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    Deoptimizer::BailoutType bailout_type, CRegister cr = cr7);
212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DeoptimizeIf(Condition condition, LInstruction* instr,
213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    DeoptimizeReason deopt_reason, CRegister cr = cr7);
214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void AddToTranslation(LEnvironment* environment, Translation* translation,
216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                        LOperand* op, bool is_tagged, bool is_uint32,
217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                        int* object_index_pointer,
218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                        int* dematerialized_index_pointer);
219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register ToRegister(int index) const;
221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DoubleRegister ToDoubleRegister(int index) const;
222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MemOperand BuildSeqStringOperand(Register string, LOperand* index,
224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                   String::Encoding encoding);
225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EmitMathAbs(LMathAbs* instr);
227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64
228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EmitInteger32MathAbs(LMathAbs* instr);
229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Support for recording safepoint information.
232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void RecordSafepoint(LPointerMap* pointers, Safepoint::Kind kind,
233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       int arguments, Safepoint::DeoptMode mode);
234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void RecordSafepoint(Safepoint::DeoptMode mode);
236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void RecordSafepointWithRegisters(LPointerMap* pointers, int arguments,
237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    Safepoint::DeoptMode mode);
238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static Condition TokenToCondition(Token::Value op);
240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EmitGoto(int block);
241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // EmitBranch expects to be the last instruction of a block.
243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  template <class InstrType>
244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EmitBranch(InstrType instr, Condition condition, CRegister cr = cr7);
245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  template <class InstrType>
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EmitTrueBranch(InstrType instr, Condition condition, CRegister cr = cr7);
247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <class InstrType>
248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EmitFalseBranch(InstrType instr, Condition condition,
249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       CRegister cr = cr7);
250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EmitNumberUntagD(LNumberUntagD* instr, Register input,
251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                        DoubleRegister result, NumberUntagDMode mode);
252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Emits optimized code for typeof x == "y".  Modifies input register.
254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Returns the condition on which a final split to
255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // true and false label should be made, to optimize fallthrough.
256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Condition EmitTypeofIs(Label* true_label, Label* false_label, Register input,
257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         Handle<String> type_name);
258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Emits optimized code for %_IsString(x).  Preserves input register.
260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Returns the condition on which a final split to
261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // true and false label should be made, to optimize fallthrough.
262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Condition EmitIsString(Register input, Register temp1, Label* is_not_string,
263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         SmiCheck check_needed);
264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Emits optimized code to deep-copy the contents of statically known
266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // object graphs (e.g. object literal boilerplate).
267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EmitDeepCopy(Handle<JSObject> object, Register result, Register source,
268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                    int* offset, AllocationSiteMode mode);
269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EnsureSpaceForLazyDeopt(int space_needed) override;
271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoLoadKeyedExternalArray(LLoadKeyed* instr);
272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr);
273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoLoadKeyedFixedArray(LLoadKeyed* instr);
274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoStoreKeyedExternalArray(LStoreKeyed* instr);
275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DoStoreKeyedFixedArray(LStoreKeyed* instr);
277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  template <class T>
279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EmitVectorLoadICRegisters(T* instr);
280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ZoneList<Deoptimizer::JumpTableEntry> jump_table_;
282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Scope* const scope_;
283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ZoneList<LDeferredCode*> deferred_;
284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool frame_is_built_;
285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Builder that keeps track of safepoints in the code. The table
287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // itself is emitted at the end of the generated code.
288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  SafepointTableBuilder safepoints_;
289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compiler from a set of parallel moves to a sequential list of moves.
291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  LGapResolver resolver_;
292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Safepoint::Kind expected_safepoint_kind_;
294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class PushSafepointRegistersScope final BASE_EMBEDDED {
296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier   public:
297c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    explicit PushSafepointRegistersScope(LCodeGen* codegen);
298c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
299c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ~PushSafepointRegistersScope();
300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier   private:
302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    LCodeGen* codegen_;
303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  };
304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  friend class LDeferredCode;
306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  friend class LEnvironment;
307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  friend class SafepointGenerator;
308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DISALLOW_COPY_AND_ASSIGN(LCodeGen);
309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass LDeferredCode : public ZoneObject {
313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  explicit LDeferredCode(LCodeGen* codegen)
315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      : codegen_(codegen),
316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        external_exit_(NULL),
317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        instruction_index_(codegen->current_instruction_) {
318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    codegen->AddDeferredCode(this);
319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  virtual ~LDeferredCode() {}
322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  virtual void Generate() = 0;
323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  virtual LInstruction* instr() = 0;
324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void SetExit(Label* exit) { external_exit_ = exit; }
326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label* entry() { return &entry_; }
327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int instruction_index() const { return instruction_index_; }
329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier protected:
331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  LCodeGen* codegen() const { return codegen_; }
332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MacroAssembler* masm() const { return codegen_->masm(); }
333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  LCodeGen* codegen_;
336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label entry_;
337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label exit_;
338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label* external_exit_;
339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int instruction_index_;
340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif  // V8_CRANKSHAFT_PPC_LITHIUM_CODEGEN_PPC_H_
345