blob: 0384485f120e69448e560d283d26d33a534b4fc4 [file] [log] [blame]
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001// Copyright 2010 the V8 project authors. All rights reserved.
ager@chromium.org7c537e22008-10-16 08:43:32 +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
ager@chromium.org5ec48922009-05-05 07:25:34 +000028#ifndef V8_ARM_CODEGEN_ARM_H_
29#define V8_ARM_CODEGEN_ARM_H_
ager@chromium.org7c537e22008-10-16 08:43:32 +000030
kasperl@chromium.org71affb52009-05-26 05:44:31 +000031namespace v8 {
32namespace internal {
ager@chromium.org7c537e22008-10-16 08:43:32 +000033
34// Forward declarations
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000035class CompilationInfo;
ager@chromium.org7c537e22008-10-16 08:43:32 +000036class DeferredCode;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000037class RegisterAllocator;
38class RegisterFile;
ager@chromium.org7c537e22008-10-16 08:43:32 +000039
ager@chromium.org3bf7b912008-11-17 09:09:45 +000040enum InitState { CONST_INIT, NOT_CONST_INIT };
41enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
ager@chromium.org7c537e22008-10-16 08:43:32 +000042
ager@chromium.org3bf7b912008-11-17 09:09:45 +000043
44// -------------------------------------------------------------------------
ager@chromium.org7c537e22008-10-16 08:43:32 +000045// Reference support
46
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000047// A reference is a C++ stack-allocated object that puts a
48// reference on the virtual frame. The reference may be consumed
49// by GetValue, TakeValue, SetValue, and Codegen::UnloadReference.
50// When the lifetime (scope) of a valid reference ends, it must have
51// been consumed, and be in state UNLOADED.
ager@chromium.org7c537e22008-10-16 08:43:32 +000052class Reference BASE_EMBEDDED {
53 public:
54 // The values of the types is important, see size().
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000055 enum Type { UNLOADED = -2, ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
56 Reference(CodeGenerator* cgen,
57 Expression* expression,
58 bool persist_after_get = false);
ager@chromium.org7c537e22008-10-16 08:43:32 +000059 ~Reference();
60
61 Expression* expression() const { return expression_; }
62 Type type() const { return type_; }
63 void set_type(Type value) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000064 ASSERT_EQ(ILLEGAL, type_);
ager@chromium.org7c537e22008-10-16 08:43:32 +000065 type_ = value;
66 }
67
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000068 void set_unloaded() {
69 ASSERT_NE(ILLEGAL, type_);
70 ASSERT_NE(UNLOADED, type_);
71 type_ = UNLOADED;
72 }
ager@chromium.org3bf7b912008-11-17 09:09:45 +000073 // The size the reference takes up on the stack.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000074 int size() const {
75 return (type_ < SLOT) ? 0 : type_;
76 }
ager@chromium.org7c537e22008-10-16 08:43:32 +000077
78 bool is_illegal() const { return type_ == ILLEGAL; }
79 bool is_slot() const { return type_ == SLOT; }
80 bool is_property() const { return type_ == NAMED || type_ == KEYED; }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000081 bool is_unloaded() const { return type_ == UNLOADED; }
ager@chromium.org7c537e22008-10-16 08:43:32 +000082
83 // Return the name. Only valid for named property references.
84 Handle<String> GetName();
85
86 // Generate code to push the value of the reference on top of the
87 // expression stack. The reference is expected to be already on top of
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000088 // the expression stack, and it is consumed by the call unless the
89 // reference is for a compound assignment.
90 // If the reference is not consumed, it is left in place under its value.
ager@chromium.orgc4c92722009-11-18 14:12:51 +000091 void GetValue();
ager@chromium.org7c537e22008-10-16 08:43:32 +000092
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000093 // Generate code to pop a reference, push the value of the reference,
94 // and then spill the stack frame.
ager@chromium.orgc4c92722009-11-18 14:12:51 +000095 inline void GetValueAndSpill();
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000096
ager@chromium.org7c537e22008-10-16 08:43:32 +000097 // Generate code to store the value on top of the expression stack in the
98 // reference. The reference is expected to be immediately below the value
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000099 // on the expression stack. The value is stored in the location specified
100 // by the reference, and is left on top of the stack, after the reference
101 // is popped from beneath it (unloaded).
ager@chromium.org7c537e22008-10-16 08:43:32 +0000102 void SetValue(InitState init_state);
103
104 private:
105 CodeGenerator* cgen_;
106 Expression* expression_;
107 Type type_;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000108 // Keep the reference on the stack after get, so it can be used by set later.
109 bool persist_after_get_;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000110};
111
112
113// -------------------------------------------------------------------------
114// Code generation state
115
116// The state is passed down the AST by the code generator (and back up, in
117// the form of the state of the label pair). It is threaded through the
118// call stack. Constructing a state implicitly pushes it on the owning code
119// generator's stack of states, and destroying one implicitly pops it.
120
121class CodeGenState BASE_EMBEDDED {
122 public:
123 // Create an initial code generator state. Destroying the initial state
124 // leaves the code generator with a NULL state.
125 explicit CodeGenState(CodeGenerator* owner);
126
127 // Create a code generator state based on a code generator's current
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000128 // state. The new state has its own pair of branch labels.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000129 CodeGenState(CodeGenerator* owner,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000130 JumpTarget* true_target,
131 JumpTarget* false_target);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000132
133 // Destroy a code generator state and restore the owning code generator's
134 // previous state.
135 ~CodeGenState();
136
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000137 JumpTarget* true_target() const { return true_target_; }
138 JumpTarget* false_target() const { return false_target_; }
ager@chromium.org7c537e22008-10-16 08:43:32 +0000139
140 private:
141 CodeGenerator* owner_;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000142 JumpTarget* true_target_;
143 JumpTarget* false_target_;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000144 CodeGenState* previous_;
145};
146
147
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000148// -------------------------------------------------------------------------
ager@chromium.org7c537e22008-10-16 08:43:32 +0000149// CodeGenerator
150
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000151class CodeGenerator: public AstVisitor {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000152 public:
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000153 // Compilation mode. Either the compiler is used as the primary
154 // compiler and needs to setup everything or the compiler is used as
155 // the secondary compiler for split compilation and has to handle
156 // bailouts.
157 enum Mode {
158 PRIMARY,
159 SECONDARY
160 };
161
ager@chromium.org7c537e22008-10-16 08:43:32 +0000162 // Takes a function literal, generates code for it. This function should only
163 // be called by compiler.cc.
164 static Handle<Code> MakeCode(FunctionLiteral* fun,
165 Handle<Script> script,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000166 bool is_eval,
167 CompilationInfo* info);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000168
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000169 // Printing of AST, etc. as requested by flags.
170 static void MakeCodePrologue(FunctionLiteral* fun);
171
172 // Allocate and install the code.
173 static Handle<Code> MakeCodeEpilogue(FunctionLiteral* fun,
174 MacroAssembler* masm,
175 Code::Flags flags,
176 Handle<Script> script);
177
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +0000178#ifdef ENABLE_LOGGING_AND_PROFILING
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000179 static bool ShouldGenerateLog(Expression* type);
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +0000180#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000181
ager@chromium.org7c537e22008-10-16 08:43:32 +0000182 static void SetFunctionInfo(Handle<JSFunction> fun,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000183 FunctionLiteral* lit,
ager@chromium.org7c537e22008-10-16 08:43:32 +0000184 bool is_toplevel,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000185 Handle<Script> script);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000186
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000187 static void RecordPositions(MacroAssembler* masm, int pos);
188
ager@chromium.org7c537e22008-10-16 08:43:32 +0000189 // Accessors
190 MacroAssembler* masm() { return masm_; }
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000191 VirtualFrame* frame() const { return frame_; }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000192 Handle<Script> script() { return script_; }
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000193
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000194 bool has_valid_frame() const { return frame_ != NULL; }
195
196 // Set the virtual frame to be new_frame, with non-frame register
197 // reference counts given by non_frame_registers. The non-frame
198 // register reference counts of the old frame are returned in
199 // non_frame_registers.
200 void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers);
201
202 void DeleteFrame();
203
204 RegisterAllocator* allocator() const { return allocator_; }
205
ager@chromium.org7c537e22008-10-16 08:43:32 +0000206 CodeGenState* state() { return state_; }
207 void set_state(CodeGenState* state) { state_ = state; }
208
209 void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
210
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000211 static const int kUnknownIntValue = -1;
212
ager@chromium.org7c537e22008-10-16 08:43:32 +0000213 private:
214 // Construction/Destruction
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000215 CodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000216
217 // Accessors
218 Scope* scope() const { return scope_; }
219
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000220 // Generating deferred code.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000221 void ProcessDeferred();
222
223 bool is_eval() { return is_eval_; }
224
225 // State
226 bool has_cc() const { return cc_reg_ != al; }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000227 JumpTarget* true_target() const { return state_->true_target(); }
228 JumpTarget* false_target() const { return state_->false_target(); }
ager@chromium.org7c537e22008-10-16 08:43:32 +0000229
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000230 // We don't track loop nesting level on ARM yet.
231 int loop_nesting() const { return 0; }
ager@chromium.org7c537e22008-10-16 08:43:32 +0000232
233 // Node visitors.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000234 void VisitStatements(ZoneList<Statement*>* statements);
235
ager@chromium.org7c537e22008-10-16 08:43:32 +0000236#define DEF_VISIT(type) \
237 void Visit##type(type* node);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000238 AST_NODE_LIST(DEF_VISIT)
ager@chromium.org7c537e22008-10-16 08:43:32 +0000239#undef DEF_VISIT
240
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000241 // Visit a statement and then spill the virtual frame if control flow can
242 // reach the end of the statement (ie, it does not exit via break,
243 // continue, return, or throw). This function is used temporarily while
244 // the code generator is being transformed.
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000245 inline void VisitAndSpill(Statement* statement);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000246
247 // Visit a list of statements and then spill the virtual frame if control
248 // flow can reach the end of the list.
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000249 inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000250
ager@chromium.org7c537e22008-10-16 08:43:32 +0000251 // Main code generation function
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000252 void Generate(FunctionLiteral* fun, Mode mode, CompilationInfo* info);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000253
254 // The following are used by class Reference.
255 void LoadReference(Reference* ref);
256 void UnloadReference(Reference* ref);
257
ager@chromium.org3811b432009-10-28 14:53:37 +0000258 static MemOperand ContextOperand(Register context, int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000259 return MemOperand(context, Context::SlotOffset(index));
260 }
261
262 MemOperand SlotOperand(Slot* slot, Register tmp);
263
ager@chromium.org381abbb2009-02-25 13:23:22 +0000264 MemOperand ContextSlotOperandCheckExtensions(Slot* slot,
265 Register tmp,
266 Register tmp2,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000267 JumpTarget* slow);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000268
ager@chromium.org7c537e22008-10-16 08:43:32 +0000269 // Expressions
ager@chromium.org3811b432009-10-28 14:53:37 +0000270 static MemOperand GlobalObject() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000271 return ContextOperand(cp, Context::GLOBAL_INDEX);
272 }
273
274 void LoadCondition(Expression* x,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000275 JumpTarget* true_target,
276 JumpTarget* false_target,
ager@chromium.org7c537e22008-10-16 08:43:32 +0000277 bool force_cc);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000278 void Load(Expression* expr);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000279 void LoadGlobal();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000280 void LoadGlobalReceiver(Register scratch);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000281
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000282 // Generate code to push the value of an expression on top of the frame
283 // and then spill the frame fully to memory. This function is used
284 // temporarily while the code generator is being transformed.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000285 inline void LoadAndSpill(Expression* expression);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000286
287 // Call LoadCondition and then spill the virtual frame unless control flow
288 // cannot reach the end of the expression (ie, by emitting only
289 // unconditional jumps to the control targets).
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000290 inline void LoadConditionAndSpill(Expression* expression,
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000291 JumpTarget* true_target,
292 JumpTarget* false_target,
293 bool force_control);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000294
ager@chromium.org7c537e22008-10-16 08:43:32 +0000295 // Read a value from a slot and leave it on top of the expression stack.
296 void LoadFromSlot(Slot* slot, TypeofState typeof_state);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000297 // Store the value on top of the stack to a slot.
298 void StoreToSlot(Slot* slot, InitState init_state);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000299 // Load a keyed property, leaving it in r0. The receiver and key are
300 // passed on the stack, and remain there.
301 void EmitKeyedLoad(bool is_global);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000302
ager@chromium.org381abbb2009-02-25 13:23:22 +0000303 void LoadFromGlobalSlotCheckExtensions(Slot* slot,
304 TypeofState typeof_state,
305 Register tmp,
306 Register tmp2,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000307 JumpTarget* slow);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000308
309 // Special code for typeof expressions: Unfortunately, we must
310 // be careful when loading the expression in 'typeof'
311 // expressions. We are not allowed to throw reference errors for
312 // non-existing properties of the global object, so we must make it
313 // look like an explicit property access, instead of an access
314 // through the context chain.
315 void LoadTypeofExpression(Expression* x);
316
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000317 void ToBoolean(JumpTarget* true_target, JumpTarget* false_target);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000318
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000319 void GenericBinaryOperation(Token::Value op,
320 OverwriteMode overwrite_mode,
321 int known_rhs = kUnknownIntValue);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000322 void Comparison(Condition cc,
323 Expression* left,
324 Expression* right,
325 bool strict = false);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000326
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000327 void SmiOperation(Token::Value op,
328 Handle<Object> value,
329 bool reversed,
330 OverwriteMode mode);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000331
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000332 void CallWithArguments(ZoneList<Expression*>* arguments,
333 CallFunctionFlags flags,
334 int position);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000335
336 // Control flow
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000337 void Branch(bool if_true, JumpTarget* target);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000338 void CheckStack();
ager@chromium.org7c537e22008-10-16 08:43:32 +0000339
ager@chromium.org9085a012009-05-11 19:22:57 +0000340 struct InlineRuntimeLUT {
341 void (CodeGenerator::*method)(ZoneList<Expression*>*);
342 const char* name;
343 };
344
345 static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000346 bool CheckForInlineRuntimeCall(CallRuntime* node);
ager@chromium.org9085a012009-05-11 19:22:57 +0000347 static bool PatchInlineRuntimeEntry(Handle<String> name,
348 const InlineRuntimeLUT& new_entry,
349 InlineRuntimeLUT* old_entry);
350
ager@chromium.org3811b432009-10-28 14:53:37 +0000351 static Handle<Code> ComputeLazyCompile(int argc);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000352 void ProcessDeclarations(ZoneList<Declaration*>* declarations);
353
ager@chromium.org3811b432009-10-28 14:53:37 +0000354 static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000355
356 // Declare global variables and functions in the given array of
357 // name/value pairs.
358 void DeclareGlobals(Handle<FixedArray> pairs);
359
360 // Instantiate the function boilerplate.
361 void InstantiateBoilerplate(Handle<JSFunction> boilerplate);
362
363 // Support for type checks.
364 void GenerateIsSmi(ZoneList<Expression*>* args);
365 void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
366 void GenerateIsArray(ZoneList<Expression*>* args);
ager@chromium.org6141cbe2009-11-20 12:14:52 +0000367 void GenerateIsObject(ZoneList<Expression*>* args);
368 void GenerateIsFunction(ZoneList<Expression*>* args);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000369 void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000370
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000371 // Support for construct call checks.
372 void GenerateIsConstructCall(ZoneList<Expression*>* args);
373
ager@chromium.org7c537e22008-10-16 08:43:32 +0000374 // Support for arguments.length and arguments[?].
375 void GenerateArgumentsLength(ZoneList<Expression*>* args);
376 void GenerateArgumentsAccess(ZoneList<Expression*>* args);
377
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000378 // Support for accessing the class and value fields of an object.
379 void GenerateClassOf(ZoneList<Expression*>* args);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000380 void GenerateValueOf(ZoneList<Expression*>* args);
381 void GenerateSetValueOf(ZoneList<Expression*>* args);
382
383 // Fast support for charCodeAt(n).
384 void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
385
386 // Fast support for object equality testing.
387 void GenerateObjectEquals(ZoneList<Expression*>* args);
388
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000389 void GenerateLog(ZoneList<Expression*>* args);
390
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000391 // Fast support for Math.random().
392 void GenerateRandomPositiveSmi(ZoneList<Expression*>* args);
393
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000394 // Fast support for StringAdd.
395 void GenerateStringAdd(ZoneList<Expression*>* args);
396
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000397 // Fast support for SubString.
398 void GenerateSubString(ZoneList<Expression*>* args);
399
400 // Fast support for StringCompare.
401 void GenerateStringCompare(ZoneList<Expression*>* args);
402
403 // Support for direct calls from JavaScript to native RegExp code.
404 void GenerateRegExpExec(ZoneList<Expression*>* args);
405
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000406 // Simple condition analysis.
407 enum ConditionAnalysis {
408 ALWAYS_TRUE,
409 ALWAYS_FALSE,
410 DONT_KNOW
411 };
412 ConditionAnalysis AnalyzeCondition(Expression* cond);
413
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000414 // Methods used to indicate which source code is generated for. Source
415 // positions are collected by the assembler and emitted with the relocation
416 // information.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000417 void CodeForFunctionPosition(FunctionLiteral* fun);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000418 void CodeForReturnPosition(FunctionLiteral* fun);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000419 void CodeForStatementPosition(Statement* node);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000420 void CodeForDoWhileConditionPosition(DoWhileStatement* stmt);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000421 void CodeForSourcePosition(int pos);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000422
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000423#ifdef DEBUG
424 // True if the registers are valid for entry to a block.
425 bool HasValidEntryRegisters();
426#endif
427
ager@chromium.org7c537e22008-10-16 08:43:32 +0000428 bool is_eval_; // Tells whether code is generated for eval.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000429
ager@chromium.org7c537e22008-10-16 08:43:32 +0000430 Handle<Script> script_;
431 List<DeferredCode*> deferred_;
432
433 // Assembler
434 MacroAssembler* masm_; // to generate code
435
436 // Code generation state
437 Scope* scope_;
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000438 VirtualFrame* frame_;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000439 RegisterAllocator* allocator_;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000440 Condition cc_reg_;
441 CodeGenState* state_;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000442
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000443 // Jump targets
444 BreakTarget function_return_;
445
446 // True if the function return is shadowed (ie, jumping to the target
447 // function_return_ does not jump to the true function return, but rather
448 // to some unlinking code).
449 bool function_return_is_shadowed_;
450
ager@chromium.org9085a012009-05-11 19:22:57 +0000451 static InlineRuntimeLUT kInlineRuntimeLUT[];
452
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000453 friend class VirtualFrame;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000454 friend class JumpTarget;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000455 friend class Reference;
ager@chromium.org3811b432009-10-28 14:53:37 +0000456 friend class FastCodeGenerator;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000457 friend class FullCodeGenerator;
458 friend class FullCodeGenSyntaxChecker;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000459
460 DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
461};
462
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000463
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000464class GenericBinaryOpStub : public CodeStub {
465 public:
466 GenericBinaryOpStub(Token::Value op,
467 OverwriteMode mode,
468 int constant_rhs = CodeGenerator::kUnknownIntValue)
469 : op_(op),
470 mode_(mode),
471 constant_rhs_(constant_rhs),
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000472 specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op, constant_rhs)),
473 name_(NULL) { }
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000474
475 private:
476 Token::Value op_;
477 OverwriteMode mode_;
478 int constant_rhs_;
479 bool specialized_on_rhs_;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000480 char* name_;
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000481
482 static const int kMaxKnownRhs = 0x40000000;
483
484 // Minor key encoding in 16 bits.
485 class ModeBits: public BitField<OverwriteMode, 0, 2> {};
486 class OpBits: public BitField<Token::Value, 2, 6> {};
487 class KnownIntBits: public BitField<int, 8, 8> {};
488
489 Major MajorKey() { return GenericBinaryOp; }
490 int MinorKey() {
491 // Encode the parameters in a unique 16 bit value.
492 return OpBits::encode(op_)
493 | ModeBits::encode(mode_)
494 | KnownIntBits::encode(MinorKeyForKnownInt());
495 }
496
497 void Generate(MacroAssembler* masm);
498 void HandleNonSmiBitwiseOp(MacroAssembler* masm);
499
500 static bool RhsIsOneWeWantToOptimizeFor(Token::Value op, int constant_rhs) {
501 if (constant_rhs == CodeGenerator::kUnknownIntValue) return false;
502 if (op == Token::DIV) return constant_rhs >= 2 && constant_rhs <= 3;
503 if (op == Token::MOD) {
504 if (constant_rhs <= 1) return false;
505 if (constant_rhs <= 10) return true;
506 if (constant_rhs <= kMaxKnownRhs && IsPowerOf2(constant_rhs)) return true;
507 return false;
508 }
509 return false;
510 }
511
512 int MinorKeyForKnownInt() {
513 if (!specialized_on_rhs_) return 0;
514 if (constant_rhs_ <= 10) return constant_rhs_ + 1;
515 ASSERT(IsPowerOf2(constant_rhs_));
516 int key = 12;
517 int d = constant_rhs_;
518 while ((d & 1) == 0) {
519 key++;
520 d >>= 1;
521 }
522 return key;
523 }
524
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000525 const char* GetName();
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000526
527#ifdef DEBUG
528 void Print() {
529 if (!specialized_on_rhs_) {
530 PrintF("GenericBinaryOpStub (%s)\n", Token::String(op_));
531 } else {
532 PrintF("GenericBinaryOpStub (%s by %d)\n",
533 Token::String(op_),
534 constant_rhs_);
535 }
536 }
537#endif
538};
539
540
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000541class StringCompareStub: public CodeStub {
542 public:
543 StringCompareStub() { }
544
545 // Compare two flat ASCII strings and returns result in r0.
546 // Does not use the stack.
547 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
548 Register left,
549 Register right,
550 Register scratch1,
551 Register scratch2,
552 Register scratch3,
553 Register scratch4);
554
555 private:
556 Major MajorKey() { return StringCompare; }
557 int MinorKey() { return 0; }
558
559 void Generate(MacroAssembler* masm);
560};
561
562
ager@chromium.org7c537e22008-10-16 08:43:32 +0000563} } // namespace v8::internal
564
ager@chromium.org5ec48922009-05-05 07:25:34 +0000565#endif // V8_ARM_CODEGEN_ARM_H_