blob: dec768b361f1bb7f9c4eb897932a363620371f26 [file] [log] [blame]
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001// Copyright 2012 the V8 project authors. All rights reserved.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_IA32_LITHIUM_CODEGEN_IA32_H_
29#define V8_IA32_LITHIUM_CODEGEN_IA32_H_
30
31#include "ia32/lithium-ia32.h"
32
33#include "checks.h"
34#include "deoptimizer.h"
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +000035#include "ia32/lithium-gap-resolver-ia32.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000036#include "safepoint-table.h"
37#include "scopes.h"
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +000038#include "v8utils.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000039
40namespace v8 {
41namespace internal {
42
43// Forward declarations.
44class LDeferredCode;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000045class LGapNode;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000046class SafepointGenerator;
47
kasperl@chromium.orga5551262010-12-07 12:49:48 +000048class LCodeGen BASE_EMBEDDED {
49 public:
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000050 LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
51 : zone_(info->zone()),
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000052 chunk_(static_cast<LPlatformChunk*>(chunk)),
kasperl@chromium.orga5551262010-12-07 12:49:48 +000053 masm_(assembler),
54 info_(info),
55 current_block_(-1),
56 current_instruction_(-1),
57 instructions_(chunk->instructions()),
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000058 deoptimizations_(4, info->zone()),
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000059 jump_table_(4, info->zone()),
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000060 deoptimization_literals_(8, info->zone()),
ulan@chromium.org2e04b582013-02-21 14:06:02 +000061 prototype_maps_(0, info->zone()),
danno@chromium.orgf005df62013-04-30 16:36:45 +000062 transition_maps_(0, info->zone()),
kasperl@chromium.orga5551262010-12-07 12:49:48 +000063 inlined_function_count_(0),
karlklose@chromium.org8f806e82011-03-07 14:06:08 +000064 scope_(info->scope()),
kasperl@chromium.orga5551262010-12-07 12:49:48 +000065 status_(UNUSED),
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000066 translations_(info->zone()),
67 deferred_(8, info->zone()),
mmassi@chromium.org7028c052012-06-13 11:51:58 +000068 dynamic_frame_alignment_(false),
danno@chromium.org94b0d6f2013-02-04 13:33:20 +000069 support_aligned_spilled_doubles_(false),
erik.corry@gmail.com0511e242011-01-19 11:11:08 +000070 osr_pc_offset_(-1),
ricow@chromium.org27bf2882011-11-17 08:34:43 +000071 last_lazy_deopt_pc_(0),
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000072 frame_is_built_(false),
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000073 x87_stack_depth_(0),
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000074 safepoints_(info->zone()),
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000075 resolver_(this),
mmassi@chromium.org7028c052012-06-13 11:51:58 +000076 expected_safepoint_kind_(Safepoint::kSimple) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +000077 PopulateDeoptimizationLiteralsWithInlinedFunctions();
78 }
79
erik.corry@gmail.com0511e242011-01-19 11:11:08 +000080 // Simple accessors.
81 MacroAssembler* masm() const { return masm_; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +000082 CompilationInfo* info() const { return info_; }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000083 Isolate* isolate() const { return info_->isolate(); }
84 Factory* factory() const { return isolate()->factory(); }
85 Heap* heap() const { return isolate()->heap(); }
rossberg@chromium.org400388e2012-06-06 09:29:22 +000086 Zone* zone() const { return zone_; }
erik.corry@gmail.com0511e242011-01-19 11:11:08 +000087
ulan@chromium.org32d7dba2013-04-24 10:59:06 +000088 // TODO(svenpanne) Use this consistently.
89 int LookupDestination(int block_id) const {
90 return chunk()->LookupDestination(block_id);
91 }
92
93 bool IsNextEmittedBlock(int block_id) const {
94 return LookupDestination(block_id) == GetNextEmittedBlock();
95 }
96
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000097 bool NeedsEagerFrame() const {
98 return GetStackSlotCount() > 0 ||
99 info()->is_non_deferred_calling() ||
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000100 !info()->IsStub() ||
101 info()->requires_frame();
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000102 }
103 bool NeedsDeferredFrame() const {
104 return !NeedsEagerFrame() && info()->is_deferred_calling();
105 }
106
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000107 // Support for converting LOperands to assembler types.
108 Operand ToOperand(LOperand* op) const;
109 Register ToRegister(LOperand* op) const;
110 XMMRegister ToDoubleRegister(LOperand* op) const;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000111 bool IsX87TopOfStack(LOperand* op) const;
danno@chromium.orgbf0c8202011-12-27 10:09:42 +0000112
113 bool IsInteger32(LConstantOperand* op) const;
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000114 bool IsSmi(LConstantOperand* op) const;
danno@chromium.orgbf0c8202011-12-27 10:09:42 +0000115 Immediate ToInteger32Immediate(LOperand* op) const {
116 return Immediate(ToInteger32(LConstantOperand::cast(op)));
117 }
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000118 Immediate ToSmiImmediate(LOperand* op) const {
119 return Immediate(Smi::FromInt(ToInteger32(LConstantOperand::cast(op))));
120 }
danno@chromium.orgbf0c8202011-12-27 10:09:42 +0000121
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000122 // Support for non-sse2 (x87) floating point stack handling.
123 // These functions maintain the depth of the stack (either 0 or 1)
124 void PushX87DoubleOperand(Operand src);
125 void PushX87FloatOperand(Operand src);
126 void ReadX87Operand(Operand dst);
127 bool X87StackNonEmpty() const { return x87_stack_depth_ > 0; }
128 void PopX87();
129 void CurrentInstructionReturnsX87Result();
130 void FlushX87StackIfNecessary(LInstruction* instr);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000131
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000132 Handle<Object> ToHandle(LConstantOperand* op) const;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000133
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000134 // The operand denoting the second word (the one with a higher address) of
135 // a double stack slot.
136 Operand HighOperand(LOperand* op);
137
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000138 // Try to generate code for the entire chunk, but it may fail if the
139 // chunk contains constructs we cannot handle. Returns true if the
140 // code generation attempt succeeded.
141 bool GenerateCode();
142
143 // Finish the code by setting stack height, safepoint, and bailout
144 // information on it.
145 void FinishCode(Handle<Code> code);
146
147 // Deferred code support.
148 void DoDeferredNumberTagD(LNumberTagD* instr);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000149
150 enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 };
151 void DoDeferredNumberTagI(LInstruction* instr,
152 LOperand* value,
153 IntegerSignedness signedness);
154
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000155 void DoDeferredTaggedToI(LTaggedToI* instr);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000156 void DoDeferredTaggedToINoSSE2(LTaggedToINoSSE2* instr);
157 void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr);
ager@chromium.org04921a82011-06-27 13:21:41 +0000158 void DoDeferredStackCheck(LStackCheck* instr);
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000159 void DoDeferredRandom(LRandom* instr);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000160 void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000161 void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
ulan@chromium.org967e2702012-02-28 09:49:15 +0000162 void DoDeferredAllocateObject(LAllocateObject* instr);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000163 void DoDeferredAllocate(LAllocate* instr);
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000164 void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
165 Label* map_check);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000166
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000167 void DoCheckMapCommon(Register reg, Handle<Map> map, LInstruction* instr);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000168
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000169 // Parallel move support.
170 void DoParallelMove(LParallelMove* move);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000171 void DoGap(LGap* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000172
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000173 // Emit frame translation commands for an environment.
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000174 void WriteTranslation(LEnvironment* environment,
175 Translation* translation,
176 int* arguments_index,
177 int* arguments_count);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000178
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000179 void EnsureRelocSpaceForDeoptimization();
180
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000181 // Declare methods that deal with the individual node types.
182#define DECLARE_DO(type) void Do##type(L##type* node);
183 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
184#undef DECLARE_DO
185
186 private:
187 enum Status {
188 UNUSED,
189 GENERATING,
190 DONE,
191 ABORTED
192 };
193
194 bool is_unused() const { return status_ == UNUSED; }
195 bool is_generating() const { return status_ == GENERATING; }
196 bool is_done() const { return status_ == DONE; }
197 bool is_aborted() const { return status_ == ABORTED; }
198
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000199 StrictModeFlag strict_mode_flag() const {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000200 return info()->is_classic_mode() ? kNonStrictMode : kStrictMode;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000201 }
202
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000203 LPlatformChunk* chunk() const { return chunk_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000204 Scope* scope() const { return scope_; }
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000205 HGraph* graph() const { return chunk()->graph(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000206
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000207 int GetNextEmittedBlock() const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000208
209 void EmitClassOfTest(Label* if_true,
210 Label* if_false,
211 Handle<String> class_name,
212 Register input,
213 Register temporary,
214 Register temporary2);
215
danno@chromium.org160a7b02011-04-18 15:51:38 +0000216 int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000217
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000218 void Abort(const char* reason);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000219 void FPRINTF_CHECKING Comment(const char* format, ...);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000220
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000221 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000222
223 // Code generation passes. Returns true if code generation should
224 // continue.
225 bool GeneratePrologue();
226 bool GenerateBody();
227 bool GenerateDeferredCode();
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000228 bool GenerateJumpTable();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000229 bool GenerateSafepointTable();
230
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000231 enum SafepointMode {
232 RECORD_SIMPLE_SAFEPOINT,
233 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS
234 };
235
236 void CallCode(Handle<Code> code,
237 RelocInfo::Mode mode,
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000238 LInstruction* instr);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000239
240 void CallCodeGeneric(Handle<Code> code,
241 RelocInfo::Mode mode,
242 LInstruction* instr,
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000243 SafepointMode safepoint_mode);
244
245 void CallRuntime(const Runtime::Function* fun,
246 int argc,
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000247 LInstruction* instr);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000248
249 void CallRuntime(Runtime::FunctionId id,
250 int argc,
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000251 LInstruction* instr) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000252 const Runtime::Function* function = Runtime::FunctionForId(id);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000253 CallRuntime(function, argc, instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000254 }
255
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000256 void CallRuntimeFromDeferred(Runtime::FunctionId id,
257 int argc,
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000258 LInstruction* instr,
259 LOperand* context);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000260
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000261 void LoadContextFromDeferred(LOperand* context);
262
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +0000263 enum EDIState {
264 EDI_UNINITIALIZED,
265 EDI_CONTAINS_TARGET
266 };
267
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000268 // Generate a direct call to a known function. Expects the function
269 // to be in edi.
270 void CallKnownFunction(Handle<JSFunction> function,
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000271 int formal_parameter_count,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000272 int arity,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000273 LInstruction* instr,
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +0000274 CallKind call_kind,
275 EDIState edi_state);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000276
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000277 void RecordSafepointWithLazyDeopt(LInstruction* instr,
278 SafepointMode safepoint_mode);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000279
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000280 void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
281 Safepoint::DeoptMode mode);
danno@chromium.orgaefd6072013-05-14 14:11:47 +0000282 void DeoptimizeIf(Condition cc,
283 LEnvironment* environment,
284 Deoptimizer::BailoutType bailout_type);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000285 void DeoptimizeIf(Condition cc, LEnvironment* environment);
danno@chromium.orgaefd6072013-05-14 14:11:47 +0000286 void SoftDeoptimize(LEnvironment* environment);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000287
288 void AddToTranslation(Translation* translation,
289 LOperand* op,
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000290 bool is_tagged,
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000291 bool is_uint32,
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000292 bool arguments_known,
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000293 int arguments_index,
294 int arguments_count);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +0000295 void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000296 void PopulateDeoptimizationData(Handle<Code> code);
297 int DefineDeoptimizationLiteral(Handle<Object> literal);
298
299 void PopulateDeoptimizationLiteralsWithInlinedFunctions();
300
301 Register ToRegister(int index) const;
302 XMMRegister ToDoubleRegister(int index) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000303 int ToInteger32(LConstantOperand* op) const;
danno@chromium.orgbf0c8202011-12-27 10:09:42 +0000304
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000305 double ToDouble(LConstantOperand* op) const;
danno@chromium.orgb6451162011-08-17 14:33:23 +0000306 Operand BuildFastArrayOperand(LOperand* elements_pointer,
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000307 LOperand* key,
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000308 Representation key_representation,
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000309 ElementsKind elements_kind,
ulan@chromium.org0e3f88b2012-05-22 09:16:05 +0000310 uint32_t offset,
311 uint32_t additional_index = 0);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000312
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000313 void EmitIntegerMathAbs(LMathAbs* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000314
315 // Support for recording safepoint and position information.
ager@chromium.org378b34e2011-01-28 08:04:38 +0000316 void RecordSafepoint(LPointerMap* pointers,
317 Safepoint::Kind kind,
318 int arguments,
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000319 Safepoint::DeoptMode mode);
320 void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
321 void RecordSafepoint(Safepoint::DeoptMode mode);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000322 void RecordSafepointWithRegisters(LPointerMap* pointers,
323 int arguments,
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000324 Safepoint::DeoptMode mode);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000325 void RecordPosition(int position);
326
327 static Condition TokenToCondition(Token::Value op, bool is_unsigned);
ager@chromium.org04921a82011-06-27 13:21:41 +0000328 void EmitGoto(int block);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000329 void EmitBranch(int left_block, int right_block, Condition cc);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000330 void EmitNumberUntagD(
331 Register input,
332 Register temp,
333 XMMRegister result,
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +0000334 bool allow_undefined_as_nan,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000335 bool deoptimize_on_minus_zero,
336 LEnvironment* env,
337 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000338
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000339 void EmitNumberUntagDNoSSE2(
340 Register input,
341 Register temp,
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +0000342 bool allow_undefined_as_nan,
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000343 bool deoptimize_on_minus_zero,
344 LEnvironment* env,
345 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED);
346
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000347 // Emits optimized code for typeof x == "y". Modifies input register.
348 // Returns the condition on which a final split to
349 // true and false label should be made, to optimize fallthrough.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000350 Condition EmitTypeofIs(Label* true_label,
351 Label* false_label,
352 Register input,
353 Handle<String> type_name);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000354
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000355 // Emits optimized code for %_IsObject(x). Preserves input register.
356 // Returns the condition on which a final split to
357 // true and false label should be made, to optimize fallthrough.
358 Condition EmitIsObject(Register input,
359 Register temp1,
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000360 Label* is_not_object,
361 Label* is_object);
362
erikcorry0ad885c2011-11-21 13:51:57 +0000363 // Emits optimized code for %_IsString(x). Preserves input register.
364 // Returns the condition on which a final split to
365 // true and false label should be made, to optimize fallthrough.
366 Condition EmitIsString(Register input,
367 Register temp1,
368 Label* is_not_string);
369
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000370 // Emits optimized code for %_IsConstructCall().
371 // Caller should branch on equal condition.
372 void EmitIsConstructCall(Register temp);
373
lrn@chromium.org1c092762011-05-09 09:42:16 +0000374 void EmitLoadFieldOrConstantFunction(Register result,
375 Register object,
376 Handle<Map> type,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000377 Handle<String> name,
378 LEnvironment* env);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000379
380 // Emits optimized code to deep-copy the contents of statically known
381 // object graphs (e.g. object literal boilerplate).
382 void EmitDeepCopy(Handle<JSObject> object,
383 Register result,
384 Register source,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000385 int* offset,
386 AllocationSiteMode mode);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000387
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000388 void EnsureSpaceForLazyDeopt();
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000389 void DoLoadKeyedExternalArray(LLoadKeyed* instr);
390 void DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr);
391 void DoLoadKeyedFixedArray(LLoadKeyed* instr);
392 void DoStoreKeyedExternalArray(LStoreKeyed* instr);
393 void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
394 void DoStoreKeyedFixedArray(LStoreKeyed* instr);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000395
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000396 void EmitReturn(LReturn* instr, bool dynamic_frame_alignment);
397
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000398 // Emits code for pushing either a tagged constant, a (non-double)
399 // register, or a stack slot operand.
400 void EmitPushTaggedOperand(LOperand* operand);
401
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000402 Zone* zone_;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000403 LPlatformChunk* const chunk_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000404 MacroAssembler* const masm_;
405 CompilationInfo* const info_;
406
407 int current_block_;
408 int current_instruction_;
409 const ZoneList<LInstruction*>* instructions_;
410 ZoneList<LEnvironment*> deoptimizations_;
danno@chromium.orgaefd6072013-05-14 14:11:47 +0000411 ZoneList<Deoptimizer::JumpTableEntry> jump_table_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000412 ZoneList<Handle<Object> > deoptimization_literals_;
ulan@chromium.org2e04b582013-02-21 14:06:02 +0000413 ZoneList<Handle<Map> > prototype_maps_;
danno@chromium.orgf005df62013-04-30 16:36:45 +0000414 ZoneList<Handle<Map> > transition_maps_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000415 int inlined_function_count_;
416 Scope* const scope_;
417 Status status_;
418 TranslationBuffer translations_;
419 ZoneList<LDeferredCode*> deferred_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000420 bool dynamic_frame_alignment_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000421 bool support_aligned_spilled_doubles_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000422 int osr_pc_offset_;
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000423 int last_lazy_deopt_pc_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000424 bool frame_is_built_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000425 int x87_stack_depth_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000426
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000427 // Builder that keeps track of safepoints in the code. The table
428 // itself is emitted at the end of the generated code.
429 SafepointTableBuilder safepoints_;
430
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000431 // Compiler from a set of parallel moves to a sequential list of moves.
432 LGapResolver resolver_;
433
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000434 Safepoint::Kind expected_safepoint_kind_;
435
436 class PushSafepointRegistersScope BASE_EMBEDDED {
437 public:
438 explicit PushSafepointRegistersScope(LCodeGen* codegen)
439 : codegen_(codegen) {
440 ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
441 codegen_->masm_->PushSafepointRegisters();
442 codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000443 ASSERT(codegen_->info()->is_calling());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000444 }
445
446 ~PushSafepointRegistersScope() {
447 ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters);
448 codegen_->masm_->PopSafepointRegisters();
449 codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
450 }
451
452 private:
453 LCodeGen* codegen_;
454 };
455
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000456 friend class LDeferredCode;
457 friend class LEnvironment;
458 friend class SafepointGenerator;
459 DISALLOW_COPY_AND_ASSIGN(LCodeGen);
460};
461
462
463class LDeferredCode: public ZoneObject {
464 public:
465 explicit LDeferredCode(LCodeGen* codegen)
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000466 : codegen_(codegen),
467 external_exit_(NULL),
468 instruction_index_(codegen->current_instruction_) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000469 codegen->AddDeferredCode(this);
470 }
471
472 virtual ~LDeferredCode() { }
473 virtual void Generate() = 0;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000474 virtual LInstruction* instr() = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000475
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000476 void SetExit(Label* exit) { external_exit_ = exit; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000477 Label* entry() { return &entry_; }
478 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000479 int instruction_index() const { return instruction_index_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000480
481 protected:
482 LCodeGen* codegen() const { return codegen_; }
483 MacroAssembler* masm() const { return codegen_->masm(); }
484
485 private:
486 LCodeGen* codegen_;
487 Label entry_;
488 Label exit_;
489 Label* external_exit_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000490 int instruction_index_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000491};
492
493} } // namespace v8::internal
494
495#endif // V8_IA32_LITHIUM_CODEGEN_IA32_H_