blob: 33a85c44db313be4e7a5d5255d2169c59626b849 [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
ager@chromium.org357bf652010-04-12 11:30:10 +000031#include "ic-inl.h"
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +000032#include "ast.h"
ager@chromium.org357bf652010-04-12 11:30:10 +000033
kasperl@chromium.org71affb52009-05-26 05:44:31 +000034namespace v8 {
35namespace internal {
ager@chromium.org7c537e22008-10-16 08:43:32 +000036
37// Forward declarations
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000038class CompilationInfo;
ager@chromium.org7c537e22008-10-16 08:43:32 +000039class DeferredCode;
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +000040class JumpTarget;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000041class RegisterAllocator;
42class RegisterFile;
ager@chromium.org7c537e22008-10-16 08:43:32 +000043
ager@chromium.org3bf7b912008-11-17 09:09:45 +000044enum InitState { CONST_INIT, NOT_CONST_INIT };
45enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
ager@chromium.org7c537e22008-10-16 08:43:32 +000046
ager@chromium.org3bf7b912008-11-17 09:09:45 +000047
48// -------------------------------------------------------------------------
ager@chromium.org7c537e22008-10-16 08:43:32 +000049// Reference support
50
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000051// A reference is a C++ stack-allocated object that puts a
52// reference on the virtual frame. The reference may be consumed
53// by GetValue, TakeValue, SetValue, and Codegen::UnloadReference.
54// When the lifetime (scope) of a valid reference ends, it must have
55// been consumed, and be in state UNLOADED.
ager@chromium.org7c537e22008-10-16 08:43:32 +000056class Reference BASE_EMBEDDED {
57 public:
58 // The values of the types is important, see size().
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000059 enum Type { UNLOADED = -2, ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
60 Reference(CodeGenerator* cgen,
61 Expression* expression,
62 bool persist_after_get = false);
ager@chromium.org7c537e22008-10-16 08:43:32 +000063 ~Reference();
64
65 Expression* expression() const { return expression_; }
66 Type type() const { return type_; }
67 void set_type(Type value) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000068 ASSERT_EQ(ILLEGAL, type_);
ager@chromium.org7c537e22008-10-16 08:43:32 +000069 type_ = value;
70 }
71
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000072 void set_unloaded() {
73 ASSERT_NE(ILLEGAL, type_);
74 ASSERT_NE(UNLOADED, type_);
75 type_ = UNLOADED;
76 }
ager@chromium.org3bf7b912008-11-17 09:09:45 +000077 // The size the reference takes up on the stack.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000078 int size() const {
79 return (type_ < SLOT) ? 0 : type_;
80 }
ager@chromium.org7c537e22008-10-16 08:43:32 +000081
82 bool is_illegal() const { return type_ == ILLEGAL; }
83 bool is_slot() const { return type_ == SLOT; }
84 bool is_property() const { return type_ == NAMED || type_ == KEYED; }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000085 bool is_unloaded() const { return type_ == UNLOADED; }
ager@chromium.org7c537e22008-10-16 08:43:32 +000086
87 // Return the name. Only valid for named property references.
88 Handle<String> GetName();
89
90 // Generate code to push the value of the reference on top of the
91 // expression stack. The reference is expected to be already on top of
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000092 // the expression stack, and it is consumed by the call unless the
93 // reference is for a compound assignment.
94 // If the reference is not consumed, it is left in place under its value.
ager@chromium.orgc4c92722009-11-18 14:12:51 +000095 void GetValue();
ager@chromium.org7c537e22008-10-16 08:43:32 +000096
97 // 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// -------------------------------------------------------------------------
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000149// Arguments allocation mode
150
151enum ArgumentsAllocationMode {
152 NO_ARGUMENTS_ALLOCATION,
153 EAGER_ARGUMENTS_ALLOCATION,
154 LAZY_ARGUMENTS_ALLOCATION
155};
156
157
158// Different nop operations are used by the code generator to detect certain
159// states of the generated code.
160enum NopMarkerTypes {
161 NON_MARKING_NOP = 0,
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000162 PROPERTY_ACCESS_INLINED
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000163};
164
165
166// -------------------------------------------------------------------------
ager@chromium.org7c537e22008-10-16 08:43:32 +0000167// CodeGenerator
168
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000169class CodeGenerator: public AstVisitor {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000170 public:
171 // Takes a function literal, generates code for it. This function should only
172 // be called by compiler.cc.
ager@chromium.org5c838252010-02-19 08:53:10 +0000173 static Handle<Code> MakeCode(CompilationInfo* info);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000174
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000175 // Printing of AST, etc. as requested by flags.
ager@chromium.org5c838252010-02-19 08:53:10 +0000176 static void MakeCodePrologue(CompilationInfo* info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000177
178 // Allocate and install the code.
ager@chromium.org5c838252010-02-19 08:53:10 +0000179 static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000180 Code::Flags flags,
ager@chromium.org5c838252010-02-19 08:53:10 +0000181 CompilationInfo* info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000182
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +0000183#ifdef ENABLE_LOGGING_AND_PROFILING
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000184 static bool ShouldGenerateLog(Expression* type);
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +0000185#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000186
ager@chromium.org7c537e22008-10-16 08:43:32 +0000187 static void SetFunctionInfo(Handle<JSFunction> fun,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000188 FunctionLiteral* lit,
ager@chromium.org7c537e22008-10-16 08:43:32 +0000189 bool is_toplevel,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000190 Handle<Script> script);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000191
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000192 static void RecordPositions(MacroAssembler* masm, int pos);
193
ager@chromium.org7c537e22008-10-16 08:43:32 +0000194 // Accessors
195 MacroAssembler* masm() { return masm_; }
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000196 VirtualFrame* frame() const { return frame_; }
ager@chromium.org5c838252010-02-19 08:53:10 +0000197 inline Handle<Script> script();
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000198
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000199 bool has_valid_frame() const { return frame_ != NULL; }
200
201 // Set the virtual frame to be new_frame, with non-frame register
202 // reference counts given by non_frame_registers. The non-frame
203 // register reference counts of the old frame are returned in
204 // non_frame_registers.
205 void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers);
206
207 void DeleteFrame();
208
209 RegisterAllocator* allocator() const { return allocator_; }
210
ager@chromium.org7c537e22008-10-16 08:43:32 +0000211 CodeGenState* state() { return state_; }
212 void set_state(CodeGenState* state) { state_ = state; }
213
214 void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
215
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000216 static const int kUnknownIntValue = -1;
217
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000218 // If the name is an inline runtime function call return the number of
219 // expected arguments. Otherwise return -1.
220 static int InlineRuntimeCallArgumentsCount(Handle<String> name);
221
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000222 // Constants related to patching of inlined load/store.
223 static const int kInlinedKeyedLoadInstructionsAfterPatchSize = 19;
224
ager@chromium.org7c537e22008-10-16 08:43:32 +0000225 private:
226 // Construction/Destruction
ager@chromium.org5c838252010-02-19 08:53:10 +0000227 explicit CodeGenerator(MacroAssembler* masm);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000228
229 // Accessors
ager@chromium.org5c838252010-02-19 08:53:10 +0000230 inline bool is_eval();
sgjesse@chromium.org833cdd72010-02-26 10:06:16 +0000231 inline Scope* scope();
ager@chromium.org7c537e22008-10-16 08:43:32 +0000232
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000233 // Generating deferred code.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000234 void ProcessDeferred();
235
ager@chromium.org7c537e22008-10-16 08:43:32 +0000236 // State
237 bool has_cc() const { return cc_reg_ != al; }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000238 JumpTarget* true_target() const { return state_->true_target(); }
239 JumpTarget* false_target() const { return state_->false_target(); }
ager@chromium.org7c537e22008-10-16 08:43:32 +0000240
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000241 // Track loop nesting level.
242 int loop_nesting() const { return loop_nesting_; }
243 void IncrementLoopNesting() { loop_nesting_++; }
244 void DecrementLoopNesting() { loop_nesting_--; }
ager@chromium.org7c537e22008-10-16 08:43:32 +0000245
246 // Node visitors.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000247 void VisitStatements(ZoneList<Statement*>* statements);
248
ager@chromium.org7c537e22008-10-16 08:43:32 +0000249#define DEF_VISIT(type) \
250 void Visit##type(type* node);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000251 AST_NODE_LIST(DEF_VISIT)
ager@chromium.org7c537e22008-10-16 08:43:32 +0000252#undef DEF_VISIT
253
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000254 // Visit a statement and then spill the virtual frame if control flow can
255 // reach the end of the statement (ie, it does not exit via break,
256 // continue, return, or throw). This function is used temporarily while
257 // the code generator is being transformed.
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000258 inline void VisitAndSpill(Statement* statement);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000259
260 // Visit a list of statements and then spill the virtual frame if control
261 // flow can reach the end of the list.
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000262 inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000263
ager@chromium.org7c537e22008-10-16 08:43:32 +0000264 // Main code generation function
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +0000265 void Generate(CompilationInfo* info);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000266
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000267 // Returns the arguments allocation mode.
268 ArgumentsAllocationMode ArgumentsMode();
269
270 // Store the arguments object and allocate it if necessary.
271 void StoreArgumentsObject(bool initial);
272
ager@chromium.org7c537e22008-10-16 08:43:32 +0000273 // The following are used by class Reference.
274 void LoadReference(Reference* ref);
275 void UnloadReference(Reference* ref);
276
ager@chromium.org3811b432009-10-28 14:53:37 +0000277 static MemOperand ContextOperand(Register context, int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000278 return MemOperand(context, Context::SlotOffset(index));
279 }
280
281 MemOperand SlotOperand(Slot* slot, Register tmp);
282
ager@chromium.org381abbb2009-02-25 13:23:22 +0000283 MemOperand ContextSlotOperandCheckExtensions(Slot* slot,
284 Register tmp,
285 Register tmp2,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000286 JumpTarget* slow);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000287
ager@chromium.org7c537e22008-10-16 08:43:32 +0000288 // Expressions
ager@chromium.org3811b432009-10-28 14:53:37 +0000289 static MemOperand GlobalObject() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000290 return ContextOperand(cp, Context::GLOBAL_INDEX);
291 }
292
293 void LoadCondition(Expression* x,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000294 JumpTarget* true_target,
295 JumpTarget* false_target,
ager@chromium.org7c537e22008-10-16 08:43:32 +0000296 bool force_cc);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000297 void Load(Expression* expr);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000298 void LoadGlobal();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000299 void LoadGlobalReceiver(Register scratch);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000300
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000301 // Generate code to push the value of an expression on top of the frame
302 // and then spill the frame fully to memory. This function is used
303 // temporarily while the code generator is being transformed.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000304 inline void LoadAndSpill(Expression* expression);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000305
306 // Call LoadCondition and then spill the virtual frame unless control flow
307 // cannot reach the end of the expression (ie, by emitting only
308 // unconditional jumps to the control targets).
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000309 inline void LoadConditionAndSpill(Expression* expression,
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000310 JumpTarget* true_target,
311 JumpTarget* false_target,
312 bool force_control);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000313
ager@chromium.org7c537e22008-10-16 08:43:32 +0000314 // Read a value from a slot and leave it on top of the expression stack.
315 void LoadFromSlot(Slot* slot, TypeofState typeof_state);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000316 void LoadFromSlotCheckForArguments(Slot* slot, TypeofState state);
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000317
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000318 // Store the value on top of the stack to a slot.
319 void StoreToSlot(Slot* slot, InitState init_state);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000320
ager@chromium.orgac091b72010-05-05 07:34:42 +0000321 // Support for compiling assignment expressions.
322 void EmitSlotAssignment(Assignment* node);
323 void EmitNamedPropertyAssignment(Assignment* node);
324 void EmitKeyedPropertyAssignment(Assignment* node);
325
326 // Load a named property, returning it in r0. The receiver is passed on the
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000327 // stack, and remains there.
328 void EmitNamedLoad(Handle<String> name, bool is_contextual);
329
ager@chromium.orgac091b72010-05-05 07:34:42 +0000330 // Store to a named property. If the store is contextual, value is passed on
331 // the frame and consumed. Otherwise, receiver and value are passed on the
332 // frame and consumed. The result is returned in r0.
333 void EmitNamedStore(Handle<String> name, bool is_contextual);
334
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000335 // Load a keyed property, leaving it in r0. The receiver and key are
336 // passed on the stack, and remain there.
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000337 void EmitKeyedLoad();
338
339 // Store a keyed property. Key and receiver are on the stack and the value is
340 // in r0. Result is returned in r0.
341 void EmitKeyedStore(StaticType* key_type);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000342
ager@chromium.org381abbb2009-02-25 13:23:22 +0000343 void LoadFromGlobalSlotCheckExtensions(Slot* slot,
344 TypeofState typeof_state,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000345 JumpTarget* slow);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000346
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000347 // Support for loading from local/global variables and arguments
348 // whose location is known unless they are shadowed by
349 // eval-introduced bindings. Generates no code for unsupported slot
350 // types and therefore expects to fall through to the slow jump target.
351 void EmitDynamicLoadFromSlotFastCase(Slot* slot,
352 TypeofState typeof_state,
353 JumpTarget* slow,
354 JumpTarget* done);
355
ager@chromium.org7c537e22008-10-16 08:43:32 +0000356 // Special code for typeof expressions: Unfortunately, we must
357 // be careful when loading the expression in 'typeof'
358 // expressions. We are not allowed to throw reference errors for
359 // non-existing properties of the global object, so we must make it
360 // look like an explicit property access, instead of an access
361 // through the context chain.
362 void LoadTypeofExpression(Expression* x);
363
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000364 void ToBoolean(JumpTarget* true_target, JumpTarget* false_target);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000365
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000366 // Generate code that computes a shortcutting logical operation.
367 void GenerateLogicalBooleanOperation(BinaryOperation* node);
368
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000369 void GenericBinaryOperation(Token::Value op,
370 OverwriteMode overwrite_mode,
371 int known_rhs = kUnknownIntValue);
ager@chromium.org357bf652010-04-12 11:30:10 +0000372 void VirtualFrameBinaryOperation(Token::Value op,
373 OverwriteMode overwrite_mode,
374 int known_rhs = kUnknownIntValue);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000375 void Comparison(Condition cc,
376 Expression* left,
377 Expression* right,
378 bool strict = false);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000379
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000380 void SmiOperation(Token::Value op,
381 Handle<Object> value,
382 bool reversed,
383 OverwriteMode mode);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000384
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000385 void CallWithArguments(ZoneList<Expression*>* arguments,
386 CallFunctionFlags flags,
387 int position);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000388
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000389 // An optimized implementation of expressions of the form
390 // x.apply(y, arguments). We call x the applicand and y the receiver.
391 // The optimization avoids allocating an arguments object if possible.
392 void CallApplyLazy(Expression* applicand,
393 Expression* receiver,
394 VariableProxy* arguments,
395 int position);
396
ager@chromium.org7c537e22008-10-16 08:43:32 +0000397 // Control flow
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000398 void Branch(bool if_true, JumpTarget* target);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000399 void CheckStack();
ager@chromium.org7c537e22008-10-16 08:43:32 +0000400
ager@chromium.org9085a012009-05-11 19:22:57 +0000401 struct InlineRuntimeLUT {
402 void (CodeGenerator::*method)(ZoneList<Expression*>*);
403 const char* name;
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000404 int nargs;
ager@chromium.org9085a012009-05-11 19:22:57 +0000405 };
406
407 static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000408 bool CheckForInlineRuntimeCall(CallRuntime* node);
ager@chromium.org9085a012009-05-11 19:22:57 +0000409 static bool PatchInlineRuntimeEntry(Handle<String> name,
410 const InlineRuntimeLUT& new_entry,
411 InlineRuntimeLUT* old_entry);
412
ager@chromium.org3811b432009-10-28 14:53:37 +0000413 static Handle<Code> ComputeLazyCompile(int argc);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000414 void ProcessDeclarations(ZoneList<Declaration*>* declarations);
415
ager@chromium.org3811b432009-10-28 14:53:37 +0000416 static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000417
418 // Declare global variables and functions in the given array of
419 // name/value pairs.
420 void DeclareGlobals(Handle<FixedArray> pairs);
421
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000422 // Instantiate the function based on the shared function info.
423 void InstantiateFunction(Handle<SharedFunctionInfo> function_info);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000424
425 // Support for type checks.
426 void GenerateIsSmi(ZoneList<Expression*>* args);
427 void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
428 void GenerateIsArray(ZoneList<Expression*>* args);
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +0000429 void GenerateIsRegExp(ZoneList<Expression*>* args);
ager@chromium.org6141cbe2009-11-20 12:14:52 +0000430 void GenerateIsObject(ZoneList<Expression*>* args);
431 void GenerateIsFunction(ZoneList<Expression*>* args);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000432 void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000433
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000434 // Support for construct call checks.
435 void GenerateIsConstructCall(ZoneList<Expression*>* args);
436
ager@chromium.org7c537e22008-10-16 08:43:32 +0000437 // Support for arguments.length and arguments[?].
438 void GenerateArgumentsLength(ZoneList<Expression*>* args);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000439 void GenerateArguments(ZoneList<Expression*>* args);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000440
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000441 // Support for accessing the class and value fields of an object.
442 void GenerateClassOf(ZoneList<Expression*>* args);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000443 void GenerateValueOf(ZoneList<Expression*>* args);
444 void GenerateSetValueOf(ZoneList<Expression*>* args);
445
446 // Fast support for charCodeAt(n).
447 void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
448
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000449 // Fast support for string.charAt(n) and string[n].
450 void GenerateCharFromCode(ZoneList<Expression*>* args);
451
ager@chromium.org7c537e22008-10-16 08:43:32 +0000452 // Fast support for object equality testing.
453 void GenerateObjectEquals(ZoneList<Expression*>* args);
454
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000455 void GenerateLog(ZoneList<Expression*>* args);
456
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000457 // Fast support for Math.random().
ager@chromium.org357bf652010-04-12 11:30:10 +0000458 void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000459
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000460 // Fast support for StringAdd.
461 void GenerateStringAdd(ZoneList<Expression*>* args);
462
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000463 // Fast support for SubString.
464 void GenerateSubString(ZoneList<Expression*>* args);
465
466 // Fast support for StringCompare.
467 void GenerateStringCompare(ZoneList<Expression*>* args);
468
469 // Support for direct calls from JavaScript to native RegExp code.
470 void GenerateRegExpExec(ZoneList<Expression*>* args);
471
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000472 void GenerateRegExpConstructResult(ZoneList<Expression*>* args);
473
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000474 // Support for fast native caches.
475 void GenerateGetFromCache(ZoneList<Expression*>* args);
476
ager@chromium.org5c838252010-02-19 08:53:10 +0000477 // Fast support for number to string.
478 void GenerateNumberToString(ZoneList<Expression*>* args);
479
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000480 // Fast swapping of elements.
481 void GenerateSwapElements(ZoneList<Expression*>* args);
482
ager@chromium.org357bf652010-04-12 11:30:10 +0000483 // Fast call for custom callbacks.
484 void GenerateCallFunction(ZoneList<Expression*>* args);
485
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000486 // Fast call to math functions.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000487 void GenerateMathPow(ZoneList<Expression*>* args);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000488 void GenerateMathSin(ZoneList<Expression*>* args);
489 void GenerateMathCos(ZoneList<Expression*>* args);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000490 void GenerateMathSqrt(ZoneList<Expression*>* args);
491
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000492 // Simple condition analysis.
493 enum ConditionAnalysis {
494 ALWAYS_TRUE,
495 ALWAYS_FALSE,
496 DONT_KNOW
497 };
498 ConditionAnalysis AnalyzeCondition(Expression* cond);
499
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000500 // Methods used to indicate which source code is generated for. Source
501 // positions are collected by the assembler and emitted with the relocation
502 // information.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000503 void CodeForFunctionPosition(FunctionLiteral* fun);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000504 void CodeForReturnPosition(FunctionLiteral* fun);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000505 void CodeForStatementPosition(Statement* node);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000506 void CodeForDoWhileConditionPosition(DoWhileStatement* stmt);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000507 void CodeForSourcePosition(int pos);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000508
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000509#ifdef DEBUG
510 // True if the registers are valid for entry to a block.
511 bool HasValidEntryRegisters();
512#endif
513
ager@chromium.org7c537e22008-10-16 08:43:32 +0000514 List<DeferredCode*> deferred_;
515
516 // Assembler
517 MacroAssembler* masm_; // to generate code
518
ager@chromium.org5c838252010-02-19 08:53:10 +0000519 CompilationInfo* info_;
520
ager@chromium.org7c537e22008-10-16 08:43:32 +0000521 // Code generation state
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000522 VirtualFrame* frame_;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000523 RegisterAllocator* allocator_;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000524 Condition cc_reg_;
525 CodeGenState* state_;
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000526 int loop_nesting_;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000527
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000528 // Jump targets
529 BreakTarget function_return_;
530
531 // True if the function return is shadowed (ie, jumping to the target
532 // function_return_ does not jump to the true function return, but rather
533 // to some unlinking code).
534 bool function_return_is_shadowed_;
535
ager@chromium.org9085a012009-05-11 19:22:57 +0000536 static InlineRuntimeLUT kInlineRuntimeLUT[];
537
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000538 friend class VirtualFrame;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000539 friend class JumpTarget;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000540 friend class Reference;
ager@chromium.org3811b432009-10-28 14:53:37 +0000541 friend class FastCodeGenerator;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000542 friend class FullCodeGenerator;
543 friend class FullCodeGenSyntaxChecker;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000544
545 DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
546};
547
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000548
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000549class GenericBinaryOpStub : public CodeStub {
550 public:
551 GenericBinaryOpStub(Token::Value op,
552 OverwriteMode mode,
ager@chromium.org357bf652010-04-12 11:30:10 +0000553 Register lhs,
554 Register rhs,
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000555 int constant_rhs = CodeGenerator::kUnknownIntValue)
556 : op_(op),
557 mode_(mode),
ager@chromium.org357bf652010-04-12 11:30:10 +0000558 lhs_(lhs),
559 rhs_(rhs),
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000560 constant_rhs_(constant_rhs),
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000561 specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op, constant_rhs)),
ager@chromium.org357bf652010-04-12 11:30:10 +0000562 runtime_operands_type_(BinaryOpIC::DEFAULT),
563 name_(NULL) { }
564
565 GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info)
566 : op_(OpBits::decode(key)),
567 mode_(ModeBits::decode(key)),
568 lhs_(LhsRegister(RegisterBits::decode(key))),
569 rhs_(RhsRegister(RegisterBits::decode(key))),
570 constant_rhs_(KnownBitsForMinorKey(KnownIntBits::decode(key))),
571 specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op_, constant_rhs_)),
572 runtime_operands_type_(type_info),
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000573 name_(NULL) { }
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000574
575 private:
576 Token::Value op_;
577 OverwriteMode mode_;
ager@chromium.org357bf652010-04-12 11:30:10 +0000578 Register lhs_;
579 Register rhs_;
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000580 int constant_rhs_;
581 bool specialized_on_rhs_;
ager@chromium.org357bf652010-04-12 11:30:10 +0000582 BinaryOpIC::TypeInfo runtime_operands_type_;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000583 char* name_;
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000584
585 static const int kMaxKnownRhs = 0x40000000;
ager@chromium.org357bf652010-04-12 11:30:10 +0000586 static const int kKnownRhsKeyBits = 6;
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000587
ager@chromium.org357bf652010-04-12 11:30:10 +0000588 // Minor key encoding in 17 bits.
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000589 class ModeBits: public BitField<OverwriteMode, 0, 2> {};
590 class OpBits: public BitField<Token::Value, 2, 6> {};
ager@chromium.org357bf652010-04-12 11:30:10 +0000591 class TypeInfoBits: public BitField<int, 8, 2> {};
592 class RegisterBits: public BitField<bool, 10, 1> {};
593 class KnownIntBits: public BitField<int, 11, kKnownRhsKeyBits> {};
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000594
595 Major MajorKey() { return GenericBinaryOp; }
596 int MinorKey() {
ager@chromium.org357bf652010-04-12 11:30:10 +0000597 ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
598 (lhs_.is(r1) && rhs_.is(r0)));
599 // Encode the parameters in a unique 18 bit value.
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000600 return OpBits::encode(op_)
601 | ModeBits::encode(mode_)
ager@chromium.org357bf652010-04-12 11:30:10 +0000602 | KnownIntBits::encode(MinorKeyForKnownInt())
603 | TypeInfoBits::encode(runtime_operands_type_)
604 | RegisterBits::encode(lhs_.is(r0));
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000605 }
606
607 void Generate(MacroAssembler* masm);
ager@chromium.org357bf652010-04-12 11:30:10 +0000608 void HandleNonSmiBitwiseOp(MacroAssembler* masm, Register lhs, Register rhs);
609 void HandleBinaryOpSlowCases(MacroAssembler* masm,
610 Label* not_smi,
611 Register lhs,
612 Register rhs,
613 const Builtins::JavaScript& builtin);
614 void GenerateTypeTransition(MacroAssembler* masm);
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000615
616 static bool RhsIsOneWeWantToOptimizeFor(Token::Value op, int constant_rhs) {
617 if (constant_rhs == CodeGenerator::kUnknownIntValue) return false;
618 if (op == Token::DIV) return constant_rhs >= 2 && constant_rhs <= 3;
619 if (op == Token::MOD) {
620 if (constant_rhs <= 1) return false;
621 if (constant_rhs <= 10) return true;
622 if (constant_rhs <= kMaxKnownRhs && IsPowerOf2(constant_rhs)) return true;
623 return false;
624 }
625 return false;
626 }
627
628 int MinorKeyForKnownInt() {
629 if (!specialized_on_rhs_) return 0;
630 if (constant_rhs_ <= 10) return constant_rhs_ + 1;
631 ASSERT(IsPowerOf2(constant_rhs_));
632 int key = 12;
633 int d = constant_rhs_;
634 while ((d & 1) == 0) {
635 key++;
636 d >>= 1;
637 }
ager@chromium.org357bf652010-04-12 11:30:10 +0000638 ASSERT(key >= 0 && key < (1 << kKnownRhsKeyBits));
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000639 return key;
640 }
641
ager@chromium.org357bf652010-04-12 11:30:10 +0000642 int KnownBitsForMinorKey(int key) {
643 if (!key) return 0;
644 if (key <= 11) return key - 1;
645 int d = 1;
646 while (key != 12) {
647 key--;
648 d <<= 1;
649 }
650 return d;
651 }
652
653 Register LhsRegister(bool lhs_is_r0) {
654 return lhs_is_r0 ? r0 : r1;
655 }
656
657 Register RhsRegister(bool lhs_is_r0) {
658 return lhs_is_r0 ? r1 : r0;
659 }
660
661 bool ShouldGenerateSmiCode() {
662 return ((op_ != Token::DIV && op_ != Token::MOD) || specialized_on_rhs_) &&
663 runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS &&
664 runtime_operands_type_ != BinaryOpIC::STRINGS;
665 }
666
667 bool ShouldGenerateFPCode() {
668 return runtime_operands_type_ != BinaryOpIC::STRINGS;
669 }
670
671 virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
672
673 virtual InlineCacheState GetICState() {
674 return BinaryOpIC::ToState(runtime_operands_type_);
675 }
676
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000677 const char* GetName();
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000678
679#ifdef DEBUG
680 void Print() {
681 if (!specialized_on_rhs_) {
682 PrintF("GenericBinaryOpStub (%s)\n", Token::String(op_));
683 } else {
684 PrintF("GenericBinaryOpStub (%s by %d)\n",
685 Token::String(op_),
686 constant_rhs_);
687 }
688 }
689#endif
690};
691
692
ager@chromium.orgac091b72010-05-05 07:34:42 +0000693class StringHelper : public AllStatic {
ager@chromium.org5c838252010-02-19 08:53:10 +0000694 public:
ager@chromium.orgac091b72010-05-05 07:34:42 +0000695 // Generates fast code for getting a char code out of a string
696 // object at the given index. May bail out for four reasons (in the
697 // listed order):
698 // * Receiver is not a string (receiver_not_string label).
699 // * Index is not a smi (index_not_smi label).
700 // * Index is out of range (index_out_of_range).
701 // * Some other reason (slow_case label). In this case it's
702 // guaranteed that the above conditions are not violated,
703 // e.g. it's safe to assume the receiver is a string and the
704 // index is a non-negative smi < length.
705 // When successful, object, index, and scratch are clobbered.
706 // Otherwise, scratch and result are clobbered.
707 static void GenerateFastCharCodeAt(MacroAssembler* masm,
708 Register object,
709 Register index,
710 Register scratch,
711 Register result,
712 Label* receiver_not_string,
713 Label* index_not_smi,
714 Label* index_out_of_range,
715 Label* slow_case);
716
717 // Generates code for creating a one-char string from the given char
718 // code. May do a runtime call, so any register can be clobbered
719 // and, if the given invoke flag specifies a call, an internal frame
720 // is required. In tail call mode the result must be r0 register.
721 static void GenerateCharFromCode(MacroAssembler* masm,
722 Register code,
723 Register scratch,
724 Register result,
725 InvokeFlag flag);
726
ager@chromium.org5c838252010-02-19 08:53:10 +0000727 // Generate code for copying characters using a simple loop. This should only
728 // be used in places where the number of characters is small and the
729 // additional setup and checking in GenerateCopyCharactersLong adds too much
730 // overhead. Copying of overlapping regions is not supported.
731 // Dest register ends at the position after the last character written.
ager@chromium.orgac091b72010-05-05 07:34:42 +0000732 static void GenerateCopyCharacters(MacroAssembler* masm,
733 Register dest,
734 Register src,
735 Register count,
736 Register scratch,
737 bool ascii);
ager@chromium.org5c838252010-02-19 08:53:10 +0000738
739 // Generate code for copying a large number of characters. This function
740 // is allowed to spend extra time setting up conditions to make copying
741 // faster. Copying of overlapping regions is not supported.
742 // Dest register ends at the position after the last character written.
ager@chromium.orgac091b72010-05-05 07:34:42 +0000743 static void GenerateCopyCharactersLong(MacroAssembler* masm,
744 Register dest,
745 Register src,
746 Register count,
747 Register scratch1,
748 Register scratch2,
749 Register scratch3,
750 Register scratch4,
751 Register scratch5,
752 int flags);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000753
754
755 // Probe the symbol table for a two character string. If the string is
756 // not found by probing a jump to the label not_found is performed. This jump
757 // does not guarantee that the string is not in the symbol table. If the
758 // string is found the code falls through with the string in register r0.
759 // Contents of both c1 and c2 registers are modified. At the exit c1 is
760 // guaranteed to contain halfword with low and high bytes equal to
761 // initial contents of c1 and c2 respectively.
ager@chromium.orgac091b72010-05-05 07:34:42 +0000762 static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
763 Register c1,
764 Register c2,
765 Register scratch1,
766 Register scratch2,
767 Register scratch3,
768 Register scratch4,
769 Register scratch5,
770 Label* not_found);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000771
772 // Generate string hash.
ager@chromium.orgac091b72010-05-05 07:34:42 +0000773 static void GenerateHashInit(MacroAssembler* masm,
774 Register hash,
775 Register character);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000776
ager@chromium.orgac091b72010-05-05 07:34:42 +0000777 static void GenerateHashAddCharacter(MacroAssembler* masm,
778 Register hash,
779 Register character);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000780
ager@chromium.orgac091b72010-05-05 07:34:42 +0000781 static void GenerateHashGetHash(MacroAssembler* masm,
782 Register hash);
783
784 private:
785 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
ager@chromium.org5c838252010-02-19 08:53:10 +0000786};
787
788
789// Flag that indicates how to generate code for the stub StringAddStub.
790enum StringAddFlags {
791 NO_STRING_ADD_FLAGS = 0,
792 NO_STRING_CHECK_IN_STUB = 1 << 0 // Omit string check in stub.
793};
794
795
ager@chromium.orgac091b72010-05-05 07:34:42 +0000796class StringAddStub: public CodeStub {
ager@chromium.org5c838252010-02-19 08:53:10 +0000797 public:
798 explicit StringAddStub(StringAddFlags flags) {
799 string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0);
800 }
801
802 private:
803 Major MajorKey() { return StringAdd; }
804 int MinorKey() { return string_check_ ? 0 : 1; }
805
806 void Generate(MacroAssembler* masm);
807
808 // Should the stub check whether arguments are strings?
809 bool string_check_;
810};
811
812
ager@chromium.orgac091b72010-05-05 07:34:42 +0000813class SubStringStub: public CodeStub {
ager@chromium.org5c838252010-02-19 08:53:10 +0000814 public:
815 SubStringStub() {}
816
817 private:
818 Major MajorKey() { return SubString; }
819 int MinorKey() { return 0; }
820
821 void Generate(MacroAssembler* masm);
822};
823
824
825
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000826class StringCompareStub: public CodeStub {
827 public:
828 StringCompareStub() { }
829
830 // Compare two flat ASCII strings and returns result in r0.
831 // Does not use the stack.
832 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
833 Register left,
834 Register right,
835 Register scratch1,
836 Register scratch2,
837 Register scratch3,
838 Register scratch4);
839
840 private:
841 Major MajorKey() { return StringCompare; }
842 int MinorKey() { return 0; }
843
844 void Generate(MacroAssembler* masm);
845};
846
847
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000848// This stub can convert a signed int32 to a heap number (double). It does
849// not work for int32s that are in Smi range! No GC occurs during this stub
850// so you don't have to set up the frame.
851class WriteInt32ToHeapNumberStub : public CodeStub {
852 public:
853 WriteInt32ToHeapNumberStub(Register the_int,
854 Register the_heap_number,
855 Register scratch)
856 : the_int_(the_int),
857 the_heap_number_(the_heap_number),
858 scratch_(scratch) { }
859
860 private:
861 Register the_int_;
862 Register the_heap_number_;
863 Register scratch_;
864
865 // Minor key encoding in 16 bits.
866 class IntRegisterBits: public BitField<int, 0, 4> {};
867 class HeapNumberRegisterBits: public BitField<int, 4, 4> {};
868 class ScratchRegisterBits: public BitField<int, 8, 4> {};
869
870 Major MajorKey() { return WriteInt32ToHeapNumber; }
871 int MinorKey() {
872 // Encode the parameters in a unique 16 bit value.
873 return IntRegisterBits::encode(the_int_.code())
874 | HeapNumberRegisterBits::encode(the_heap_number_.code())
875 | ScratchRegisterBits::encode(scratch_.code());
876 }
877
878 void Generate(MacroAssembler* masm);
879
880 const char* GetName() { return "WriteInt32ToHeapNumberStub"; }
881
882#ifdef DEBUG
883 void Print() { PrintF("WriteInt32ToHeapNumberStub\n"); }
884#endif
885};
886
887
fschneider@chromium.org086aac62010-03-17 13:18:24 +0000888class NumberToStringStub: public CodeStub {
889 public:
890 NumberToStringStub() { }
891
892 // Generate code to do a lookup in the number string cache. If the number in
893 // the register object is found in the cache the generated code falls through
894 // with the result in the result register. The object and the result register
895 // can be the same. If the number is not found in the cache the code jumps to
896 // the label not_found with only the content of register object unchanged.
897 static void GenerateLookupNumberStringCache(MacroAssembler* masm,
898 Register object,
899 Register result,
900 Register scratch1,
901 Register scratch2,
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000902 Register scratch3,
fschneider@chromium.org086aac62010-03-17 13:18:24 +0000903 bool object_is_smi,
904 Label* not_found);
905
906 private:
907 Major MajorKey() { return NumberToString; }
908 int MinorKey() { return 0; }
909
910 void Generate(MacroAssembler* masm);
911
912 const char* GetName() { return "NumberToStringStub"; }
913
914#ifdef DEBUG
915 void Print() {
916 PrintF("NumberToStringStub\n");
917 }
918#endif
919};
920
921
ager@chromium.orgac091b72010-05-05 07:34:42 +0000922class RecordWriteStub : public CodeStub {
923 public:
924 RecordWriteStub(Register object, Register offset, Register scratch)
925 : object_(object), offset_(offset), scratch_(scratch) { }
926
927 void Generate(MacroAssembler* masm);
928
929 private:
930 Register object_;
931 Register offset_;
932 Register scratch_;
933
934#ifdef DEBUG
935 void Print() {
936 PrintF("RecordWriteStub (object reg %d), (offset reg %d),"
937 " (scratch reg %d)\n",
938 object_.code(), offset_.code(), scratch_.code());
939 }
940#endif
941
942 // Minor key encoding in 12 bits. 4 bits for each of the three
943 // registers (object, offset and scratch) OOOOAAAASSSS.
944 class ScratchBits: public BitField<uint32_t, 0, 4> {};
945 class OffsetBits: public BitField<uint32_t, 4, 4> {};
946 class ObjectBits: public BitField<uint32_t, 8, 4> {};
947
948 Major MajorKey() { return RecordWrite; }
949
950 int MinorKey() {
951 // Encode the registers.
952 return ObjectBits::encode(object_.code()) |
953 OffsetBits::encode(offset_.code()) |
954 ScratchBits::encode(scratch_.code());
955 }
956};
957
958
ager@chromium.org7c537e22008-10-16 08:43:32 +0000959} } // namespace v8::internal
960
ager@chromium.org5ec48922009-05-05 07:25:34 +0000961#endif // V8_ARM_CODEGEN_ARM_H_