blob: cabdf007b91dc4f8ba1b7a6dbb39283660a12ca3 [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 };
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000046enum GenerateInlineSmi { DONT_GENERATE_INLINE_SMI, GENERATE_INLINE_SMI };
ager@chromium.org7c537e22008-10-16 08:43:32 +000047
ager@chromium.org3bf7b912008-11-17 09:09:45 +000048
49// -------------------------------------------------------------------------
ager@chromium.org7c537e22008-10-16 08:43:32 +000050// Reference support
51
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000052// A reference is a C++ stack-allocated object that puts a
53// reference on the virtual frame. The reference may be consumed
54// by GetValue, TakeValue, SetValue, and Codegen::UnloadReference.
55// When the lifetime (scope) of a valid reference ends, it must have
56// been consumed, and be in state UNLOADED.
ager@chromium.org7c537e22008-10-16 08:43:32 +000057class Reference BASE_EMBEDDED {
58 public:
59 // The values of the types is important, see size().
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000060 enum Type { UNLOADED = -2, ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
61 Reference(CodeGenerator* cgen,
62 Expression* expression,
63 bool persist_after_get = false);
ager@chromium.org7c537e22008-10-16 08:43:32 +000064 ~Reference();
65
66 Expression* expression() const { return expression_; }
67 Type type() const { return type_; }
68 void set_type(Type value) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000069 ASSERT_EQ(ILLEGAL, type_);
ager@chromium.org7c537e22008-10-16 08:43:32 +000070 type_ = value;
71 }
72
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000073 void set_unloaded() {
74 ASSERT_NE(ILLEGAL, type_);
75 ASSERT_NE(UNLOADED, type_);
76 type_ = UNLOADED;
77 }
ager@chromium.org3bf7b912008-11-17 09:09:45 +000078 // The size the reference takes up on the stack.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000079 int size() const {
80 return (type_ < SLOT) ? 0 : type_;
81 }
ager@chromium.org7c537e22008-10-16 08:43:32 +000082
83 bool is_illegal() const { return type_ == ILLEGAL; }
84 bool is_slot() const { return type_ == SLOT; }
85 bool is_property() const { return type_ == NAMED || type_ == KEYED; }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000086 bool is_unloaded() const { return type_ == UNLOADED; }
ager@chromium.org7c537e22008-10-16 08:43:32 +000087
88 // Return the name. Only valid for named property references.
89 Handle<String> GetName();
90
91 // Generate code to push the value of the reference on top of the
92 // expression stack. The reference is expected to be already on top of
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000093 // the expression stack, and it is consumed by the call unless the
94 // reference is for a compound assignment.
95 // If the reference is not consumed, it is left in place under its value.
ager@chromium.orgc4c92722009-11-18 14:12:51 +000096 void GetValue();
ager@chromium.org7c537e22008-10-16 08:43:32 +000097
98 // Generate code to store the value on top of the expression stack in the
99 // reference. The reference is expected to be immediately below the value
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000100 // on the expression stack. The value is stored in the location specified
101 // by the reference, and is left on top of the stack, after the reference
102 // is popped from beneath it (unloaded).
ager@chromium.org7c537e22008-10-16 08:43:32 +0000103 void SetValue(InitState init_state);
104
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000105 // This is in preparation for something that uses the reference on the stack.
106 // If we need this reference afterwards get then dup it now. Otherwise mark
107 // it as used.
108 inline void DupIfPersist();
109
ager@chromium.org7c537e22008-10-16 08:43:32 +0000110 private:
111 CodeGenerator* cgen_;
112 Expression* expression_;
113 Type type_;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000114 // Keep the reference on the stack after get, so it can be used by set later.
115 bool persist_after_get_;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000116};
117
118
119// -------------------------------------------------------------------------
120// Code generation state
121
122// The state is passed down the AST by the code generator (and back up, in
123// the form of the state of the label pair). It is threaded through the
124// call stack. Constructing a state implicitly pushes it on the owning code
125// generator's stack of states, and destroying one implicitly pops it.
126
127class CodeGenState BASE_EMBEDDED {
128 public:
129 // Create an initial code generator state. Destroying the initial state
130 // leaves the code generator with a NULL state.
131 explicit CodeGenState(CodeGenerator* owner);
132
ager@chromium.org7c537e22008-10-16 08:43:32 +0000133 // Destroy a code generator state and restore the owning code generator's
134 // previous state.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000135 virtual ~CodeGenState();
ager@chromium.org7c537e22008-10-16 08:43:32 +0000136
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000137 virtual JumpTarget* true_target() const { return NULL; }
138 virtual JumpTarget* false_target() const { return NULL; }
139
140 protected:
141 inline CodeGenerator* owner() { return owner_; }
142 inline CodeGenState* previous() const { return previous_; }
ager@chromium.org7c537e22008-10-16 08:43:32 +0000143
144 private:
145 CodeGenerator* owner_;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000146 CodeGenState* previous_;
147};
148
149
150class ConditionCodeGenState : public CodeGenState {
151 public:
152 // Create a code generator state based on a code generator's current
153 // state. The new state has its own pair of branch labels.
154 ConditionCodeGenState(CodeGenerator* owner,
155 JumpTarget* true_target,
156 JumpTarget* false_target);
157
158 virtual JumpTarget* true_target() const { return true_target_; }
159 virtual JumpTarget* false_target() const { return false_target_; }
160
161 private:
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000162 JumpTarget* true_target_;
163 JumpTarget* false_target_;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000164};
165
166
167class TypeInfoCodeGenState : public CodeGenState {
168 public:
169 TypeInfoCodeGenState(CodeGenerator* owner,
170 Slot* slot_number,
171 TypeInfo info);
172 ~TypeInfoCodeGenState();
173
174 virtual JumpTarget* true_target() const { return previous()->true_target(); }
175 virtual JumpTarget* false_target() const {
176 return previous()->false_target();
177 }
178
179 private:
180 Slot* slot_;
181 TypeInfo old_type_info_;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000182};
183
184
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000185// -------------------------------------------------------------------------
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000186// Arguments allocation mode
187
188enum ArgumentsAllocationMode {
189 NO_ARGUMENTS_ALLOCATION,
190 EAGER_ARGUMENTS_ALLOCATION,
191 LAZY_ARGUMENTS_ALLOCATION
192};
193
194
195// Different nop operations are used by the code generator to detect certain
196// states of the generated code.
197enum NopMarkerTypes {
198 NON_MARKING_NOP = 0,
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000199 PROPERTY_ACCESS_INLINED
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000200};
201
202
203// -------------------------------------------------------------------------
ager@chromium.org7c537e22008-10-16 08:43:32 +0000204// CodeGenerator
205
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000206class CodeGenerator: public AstVisitor {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000207 public:
208 // Takes a function literal, generates code for it. This function should only
209 // be called by compiler.cc.
ager@chromium.org5c838252010-02-19 08:53:10 +0000210 static Handle<Code> MakeCode(CompilationInfo* info);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000211
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000212 // Printing of AST, etc. as requested by flags.
ager@chromium.org5c838252010-02-19 08:53:10 +0000213 static void MakeCodePrologue(CompilationInfo* info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000214
215 // Allocate and install the code.
ager@chromium.org5c838252010-02-19 08:53:10 +0000216 static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000217 Code::Flags flags,
ager@chromium.org5c838252010-02-19 08:53:10 +0000218 CompilationInfo* info);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000219
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +0000220#ifdef ENABLE_LOGGING_AND_PROFILING
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000221 static bool ShouldGenerateLog(Expression* type);
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +0000222#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000223
ager@chromium.org7c537e22008-10-16 08:43:32 +0000224 static void SetFunctionInfo(Handle<JSFunction> fun,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000225 FunctionLiteral* lit,
ager@chromium.org7c537e22008-10-16 08:43:32 +0000226 bool is_toplevel,
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000227 Handle<Script> script);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000228
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000229 static bool RecordPositions(MacroAssembler* masm,
230 int pos,
231 bool right_here = false);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000232
ager@chromium.org7c537e22008-10-16 08:43:32 +0000233 // Accessors
234 MacroAssembler* masm() { return masm_; }
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000235 VirtualFrame* frame() const { return frame_; }
ager@chromium.org5c838252010-02-19 08:53:10 +0000236 inline Handle<Script> script();
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000237
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000238 bool has_valid_frame() const { return frame_ != NULL; }
239
240 // Set the virtual frame to be new_frame, with non-frame register
241 // reference counts given by non_frame_registers. The non-frame
242 // register reference counts of the old frame are returned in
243 // non_frame_registers.
244 void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers);
245
246 void DeleteFrame();
247
248 RegisterAllocator* allocator() const { return allocator_; }
249
ager@chromium.org7c537e22008-10-16 08:43:32 +0000250 CodeGenState* state() { return state_; }
251 void set_state(CodeGenState* state) { state_ = state; }
252
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000253 TypeInfo type_info(Slot* slot) {
254 int index = NumberOfSlot(slot);
255 if (index == kInvalidSlotNumber) return TypeInfo::Unknown();
256 return (*type_info_)[index];
257 }
258
259 TypeInfo set_type_info(Slot* slot, TypeInfo info) {
260 int index = NumberOfSlot(slot);
261 ASSERT(index >= kInvalidSlotNumber);
262 if (index != kInvalidSlotNumber) {
263 TypeInfo previous_value = (*type_info_)[index];
264 (*type_info_)[index] = info;
265 return previous_value;
266 }
267 return TypeInfo::Unknown();
268 }
269
ager@chromium.org7c537e22008-10-16 08:43:32 +0000270 void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
271
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000272 static const int kUnknownIntValue = -1;
273
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000274 // If the name is an inline runtime function call return the number of
275 // expected arguments. Otherwise return -1.
276 static int InlineRuntimeCallArgumentsCount(Handle<String> name);
277
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000278 // Constants related to patching of inlined load/store.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000279 static const int kInlinedKeyedLoadInstructionsAfterPatch = 17;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000280 static const int kInlinedKeyedStoreInstructionsAfterPatch = 5;
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000281
ager@chromium.org7c537e22008-10-16 08:43:32 +0000282 private:
283 // Construction/Destruction
ager@chromium.org5c838252010-02-19 08:53:10 +0000284 explicit CodeGenerator(MacroAssembler* masm);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000285
286 // Accessors
ager@chromium.org5c838252010-02-19 08:53:10 +0000287 inline bool is_eval();
sgjesse@chromium.org833cdd72010-02-26 10:06:16 +0000288 inline Scope* scope();
ager@chromium.org7c537e22008-10-16 08:43:32 +0000289
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000290 // Generating deferred code.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000291 void ProcessDeferred();
292
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000293 static const int kInvalidSlotNumber = -1;
294
295 int NumberOfSlot(Slot* slot);
296
ager@chromium.org7c537e22008-10-16 08:43:32 +0000297 // State
298 bool has_cc() const { return cc_reg_ != al; }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000299 JumpTarget* true_target() const { return state_->true_target(); }
300 JumpTarget* false_target() const { return state_->false_target(); }
ager@chromium.org7c537e22008-10-16 08:43:32 +0000301
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000302 // Track loop nesting level.
303 int loop_nesting() const { return loop_nesting_; }
304 void IncrementLoopNesting() { loop_nesting_++; }
305 void DecrementLoopNesting() { loop_nesting_--; }
ager@chromium.org7c537e22008-10-16 08:43:32 +0000306
307 // Node visitors.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000308 void VisitStatements(ZoneList<Statement*>* statements);
309
ager@chromium.org7c537e22008-10-16 08:43:32 +0000310#define DEF_VISIT(type) \
311 void Visit##type(type* node);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000312 AST_NODE_LIST(DEF_VISIT)
ager@chromium.org7c537e22008-10-16 08:43:32 +0000313#undef DEF_VISIT
314
315 // Main code generation function
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +0000316 void Generate(CompilationInfo* info);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000317
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000318 // Returns the arguments allocation mode.
319 ArgumentsAllocationMode ArgumentsMode();
320
321 // Store the arguments object and allocate it if necessary.
322 void StoreArgumentsObject(bool initial);
323
ager@chromium.org7c537e22008-10-16 08:43:32 +0000324 // The following are used by class Reference.
325 void LoadReference(Reference* ref);
326 void UnloadReference(Reference* ref);
327
ager@chromium.org3811b432009-10-28 14:53:37 +0000328 static MemOperand ContextOperand(Register context, int index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000329 return MemOperand(context, Context::SlotOffset(index));
330 }
331
332 MemOperand SlotOperand(Slot* slot, Register tmp);
333
ager@chromium.org381abbb2009-02-25 13:23:22 +0000334 MemOperand ContextSlotOperandCheckExtensions(Slot* slot,
335 Register tmp,
336 Register tmp2,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000337 JumpTarget* slow);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000338
ager@chromium.org7c537e22008-10-16 08:43:32 +0000339 // Expressions
ager@chromium.org3811b432009-10-28 14:53:37 +0000340 static MemOperand GlobalObject() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000341 return ContextOperand(cp, Context::GLOBAL_INDEX);
342 }
343
344 void LoadCondition(Expression* x,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000345 JumpTarget* true_target,
346 JumpTarget* false_target,
ager@chromium.org7c537e22008-10-16 08:43:32 +0000347 bool force_cc);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000348 void Load(Expression* expr);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000349 void LoadGlobal();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000350 void LoadGlobalReceiver(Register scratch);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000351
352 // Read a value from a slot and leave it on top of the expression stack.
353 void LoadFromSlot(Slot* slot, TypeofState typeof_state);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000354 void LoadFromSlotCheckForArguments(Slot* slot, TypeofState state);
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000355
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000356 // Store the value on top of the stack to a slot.
357 void StoreToSlot(Slot* slot, InitState init_state);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000358
ager@chromium.orgac091b72010-05-05 07:34:42 +0000359 // Support for compiling assignment expressions.
360 void EmitSlotAssignment(Assignment* node);
361 void EmitNamedPropertyAssignment(Assignment* node);
362 void EmitKeyedPropertyAssignment(Assignment* node);
363
364 // Load a named property, returning it in r0. The receiver is passed on the
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000365 // stack, and remains there.
366 void EmitNamedLoad(Handle<String> name, bool is_contextual);
367
ager@chromium.orgac091b72010-05-05 07:34:42 +0000368 // Store to a named property. If the store is contextual, value is passed on
369 // the frame and consumed. Otherwise, receiver and value are passed on the
370 // frame and consumed. The result is returned in r0.
371 void EmitNamedStore(Handle<String> name, bool is_contextual);
372
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000373 // Load a keyed property, leaving it in r0. The receiver and key are
374 // passed on the stack, and remain there.
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000375 void EmitKeyedLoad();
376
377 // Store a keyed property. Key and receiver are on the stack and the value is
378 // in r0. Result is returned in r0.
379 void EmitKeyedStore(StaticType* key_type);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000380
ager@chromium.org381abbb2009-02-25 13:23:22 +0000381 void LoadFromGlobalSlotCheckExtensions(Slot* slot,
382 TypeofState typeof_state,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000383 JumpTarget* slow);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000384
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000385 // Support for loading from local/global variables and arguments
386 // whose location is known unless they are shadowed by
387 // eval-introduced bindings. Generates no code for unsupported slot
388 // types and therefore expects to fall through to the slow jump target.
389 void EmitDynamicLoadFromSlotFastCase(Slot* slot,
390 TypeofState typeof_state,
391 JumpTarget* slow,
392 JumpTarget* done);
393
ager@chromium.org7c537e22008-10-16 08:43:32 +0000394 // Special code for typeof expressions: Unfortunately, we must
395 // be careful when loading the expression in 'typeof'
396 // expressions. We are not allowed to throw reference errors for
397 // non-existing properties of the global object, so we must make it
398 // look like an explicit property access, instead of an access
399 // through the context chain.
400 void LoadTypeofExpression(Expression* x);
401
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000402 void ToBoolean(JumpTarget* true_target, JumpTarget* false_target);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000403
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000404 // Generate code that computes a shortcutting logical operation.
405 void GenerateLogicalBooleanOperation(BinaryOperation* node);
406
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000407 void GenericBinaryOperation(Token::Value op,
408 OverwriteMode overwrite_mode,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000409 GenerateInlineSmi inline_smi,
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000410 int known_rhs = kUnknownIntValue);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000411 void Comparison(Condition cc,
412 Expression* left,
413 Expression* right,
414 bool strict = false);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000415
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000416 void SmiOperation(Token::Value op,
417 Handle<Object> value,
418 bool reversed,
419 OverwriteMode mode);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000420
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000421 void CallWithArguments(ZoneList<Expression*>* arguments,
422 CallFunctionFlags flags,
423 int position);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000424
fschneider@chromium.org013f3e12010-04-26 13:27:52 +0000425 // An optimized implementation of expressions of the form
426 // x.apply(y, arguments). We call x the applicand and y the receiver.
427 // The optimization avoids allocating an arguments object if possible.
428 void CallApplyLazy(Expression* applicand,
429 Expression* receiver,
430 VariableProxy* arguments,
431 int position);
432
ager@chromium.org7c537e22008-10-16 08:43:32 +0000433 // Control flow
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000434 void Branch(bool if_true, JumpTarget* target);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000435 void CheckStack();
ager@chromium.org7c537e22008-10-16 08:43:32 +0000436
ager@chromium.org9085a012009-05-11 19:22:57 +0000437 struct InlineRuntimeLUT {
438 void (CodeGenerator::*method)(ZoneList<Expression*>*);
439 const char* name;
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000440 int nargs;
ager@chromium.org9085a012009-05-11 19:22:57 +0000441 };
442
443 static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000444 bool CheckForInlineRuntimeCall(CallRuntime* node);
ager@chromium.org9085a012009-05-11 19:22:57 +0000445 static bool PatchInlineRuntimeEntry(Handle<String> name,
446 const InlineRuntimeLUT& new_entry,
447 InlineRuntimeLUT* old_entry);
448
ager@chromium.org3811b432009-10-28 14:53:37 +0000449 static Handle<Code> ComputeLazyCompile(int argc);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000450 void ProcessDeclarations(ZoneList<Declaration*>* declarations);
451
ager@chromium.org3811b432009-10-28 14:53:37 +0000452 static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000453
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000454 static Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
455
ager@chromium.org7c537e22008-10-16 08:43:32 +0000456 // Declare global variables and functions in the given array of
457 // name/value pairs.
458 void DeclareGlobals(Handle<FixedArray> pairs);
459
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000460 // Instantiate the function based on the shared function info.
461 void InstantiateFunction(Handle<SharedFunctionInfo> function_info);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000462
463 // Support for type checks.
464 void GenerateIsSmi(ZoneList<Expression*>* args);
465 void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
466 void GenerateIsArray(ZoneList<Expression*>* args);
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +0000467 void GenerateIsRegExp(ZoneList<Expression*>* args);
ager@chromium.org6141cbe2009-11-20 12:14:52 +0000468 void GenerateIsObject(ZoneList<Expression*>* args);
469 void GenerateIsFunction(ZoneList<Expression*>* args);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000470 void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000471
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000472 // Support for construct call checks.
473 void GenerateIsConstructCall(ZoneList<Expression*>* args);
474
ager@chromium.org7c537e22008-10-16 08:43:32 +0000475 // Support for arguments.length and arguments[?].
476 void GenerateArgumentsLength(ZoneList<Expression*>* args);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000477 void GenerateArguments(ZoneList<Expression*>* args);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000478
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000479 // Support for accessing the class and value fields of an object.
480 void GenerateClassOf(ZoneList<Expression*>* args);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000481 void GenerateValueOf(ZoneList<Expression*>* args);
482 void GenerateSetValueOf(ZoneList<Expression*>* args);
483
484 // Fast support for charCodeAt(n).
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000485 void GenerateStringCharCodeAt(ZoneList<Expression*>* args);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000486
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000487 // Fast support for string.charAt(n) and string[n].
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000488 void GenerateStringCharFromCode(ZoneList<Expression*>* args);
489
490 // Fast support for string.charAt(n) and string[n].
491 void GenerateStringCharAt(ZoneList<Expression*>* args);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000492
ager@chromium.org7c537e22008-10-16 08:43:32 +0000493 // Fast support for object equality testing.
494 void GenerateObjectEquals(ZoneList<Expression*>* args);
495
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000496 void GenerateLog(ZoneList<Expression*>* args);
497
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000498 // Fast support for Math.random().
ager@chromium.org357bf652010-04-12 11:30:10 +0000499 void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000500
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000501 // Fast support for StringAdd.
502 void GenerateStringAdd(ZoneList<Expression*>* args);
503
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000504 // Fast support for SubString.
505 void GenerateSubString(ZoneList<Expression*>* args);
506
507 // Fast support for StringCompare.
508 void GenerateStringCompare(ZoneList<Expression*>* args);
509
510 // Support for direct calls from JavaScript to native RegExp code.
511 void GenerateRegExpExec(ZoneList<Expression*>* args);
512
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000513 void GenerateRegExpConstructResult(ZoneList<Expression*>* args);
514
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000515 // Support for fast native caches.
516 void GenerateGetFromCache(ZoneList<Expression*>* args);
517
ager@chromium.org5c838252010-02-19 08:53:10 +0000518 // Fast support for number to string.
519 void GenerateNumberToString(ZoneList<Expression*>* args);
520
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000521 // Fast swapping of elements.
522 void GenerateSwapElements(ZoneList<Expression*>* args);
523
ager@chromium.org357bf652010-04-12 11:30:10 +0000524 // Fast call for custom callbacks.
525 void GenerateCallFunction(ZoneList<Expression*>* args);
526
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000527 // Fast call to math functions.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000528 void GenerateMathPow(ZoneList<Expression*>* args);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000529 void GenerateMathSin(ZoneList<Expression*>* args);
530 void GenerateMathCos(ZoneList<Expression*>* args);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000531 void GenerateMathSqrt(ZoneList<Expression*>* args);
532
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000533 // Simple condition analysis.
534 enum ConditionAnalysis {
535 ALWAYS_TRUE,
536 ALWAYS_FALSE,
537 DONT_KNOW
538 };
539 ConditionAnalysis AnalyzeCondition(Expression* cond);
540
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000541 // Methods used to indicate which source code is generated for. Source
542 // positions are collected by the assembler and emitted with the relocation
543 // information.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000544 void CodeForFunctionPosition(FunctionLiteral* fun);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +0000545 void CodeForReturnPosition(FunctionLiteral* fun);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000546 void CodeForStatementPosition(Statement* node);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000547 void CodeForDoWhileConditionPosition(DoWhileStatement* stmt);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000548 void CodeForSourcePosition(int pos);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000549
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000550#ifdef DEBUG
551 // True if the registers are valid for entry to a block.
552 bool HasValidEntryRegisters();
553#endif
554
ager@chromium.org7c537e22008-10-16 08:43:32 +0000555 List<DeferredCode*> deferred_;
556
557 // Assembler
558 MacroAssembler* masm_; // to generate code
559
ager@chromium.org5c838252010-02-19 08:53:10 +0000560 CompilationInfo* info_;
561
ager@chromium.org7c537e22008-10-16 08:43:32 +0000562 // Code generation state
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000563 VirtualFrame* frame_;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000564 RegisterAllocator* allocator_;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000565 Condition cc_reg_;
566 CodeGenState* state_;
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000567 int loop_nesting_;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000568
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000569 Vector<TypeInfo>* type_info_;
570
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000571 // Jump targets
572 BreakTarget function_return_;
573
574 // True if the function return is shadowed (ie, jumping to the target
575 // function_return_ does not jump to the true function return, but rather
576 // to some unlinking code).
577 bool function_return_is_shadowed_;
578
ager@chromium.org9085a012009-05-11 19:22:57 +0000579 static InlineRuntimeLUT kInlineRuntimeLUT[];
580
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000581 friend class VirtualFrame;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000582 friend class JumpTarget;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000583 friend class Reference;
ager@chromium.org3811b432009-10-28 14:53:37 +0000584 friend class FastCodeGenerator;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000585 friend class FullCodeGenerator;
586 friend class FullCodeGenSyntaxChecker;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000587
588 DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
589};
590
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000591
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000592class GenericBinaryOpStub : public CodeStub {
593 public:
594 GenericBinaryOpStub(Token::Value op,
595 OverwriteMode mode,
ager@chromium.org357bf652010-04-12 11:30:10 +0000596 Register lhs,
597 Register rhs,
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000598 int constant_rhs = CodeGenerator::kUnknownIntValue)
599 : op_(op),
600 mode_(mode),
ager@chromium.org357bf652010-04-12 11:30:10 +0000601 lhs_(lhs),
602 rhs_(rhs),
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000603 constant_rhs_(constant_rhs),
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000604 specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op, constant_rhs)),
ager@chromium.org357bf652010-04-12 11:30:10 +0000605 runtime_operands_type_(BinaryOpIC::DEFAULT),
606 name_(NULL) { }
607
608 GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info)
609 : op_(OpBits::decode(key)),
610 mode_(ModeBits::decode(key)),
611 lhs_(LhsRegister(RegisterBits::decode(key))),
612 rhs_(RhsRegister(RegisterBits::decode(key))),
613 constant_rhs_(KnownBitsForMinorKey(KnownIntBits::decode(key))),
614 specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op_, constant_rhs_)),
615 runtime_operands_type_(type_info),
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000616 name_(NULL) { }
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000617
618 private:
619 Token::Value op_;
620 OverwriteMode mode_;
ager@chromium.org357bf652010-04-12 11:30:10 +0000621 Register lhs_;
622 Register rhs_;
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000623 int constant_rhs_;
624 bool specialized_on_rhs_;
ager@chromium.org357bf652010-04-12 11:30:10 +0000625 BinaryOpIC::TypeInfo runtime_operands_type_;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000626 char* name_;
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000627
628 static const int kMaxKnownRhs = 0x40000000;
ager@chromium.org357bf652010-04-12 11:30:10 +0000629 static const int kKnownRhsKeyBits = 6;
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000630
ager@chromium.org357bf652010-04-12 11:30:10 +0000631 // Minor key encoding in 17 bits.
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000632 class ModeBits: public BitField<OverwriteMode, 0, 2> {};
633 class OpBits: public BitField<Token::Value, 2, 6> {};
ager@chromium.org357bf652010-04-12 11:30:10 +0000634 class TypeInfoBits: public BitField<int, 8, 2> {};
635 class RegisterBits: public BitField<bool, 10, 1> {};
636 class KnownIntBits: public BitField<int, 11, kKnownRhsKeyBits> {};
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000637
638 Major MajorKey() { return GenericBinaryOp; }
639 int MinorKey() {
ager@chromium.org357bf652010-04-12 11:30:10 +0000640 ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
641 (lhs_.is(r1) && rhs_.is(r0)));
642 // Encode the parameters in a unique 18 bit value.
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000643 return OpBits::encode(op_)
644 | ModeBits::encode(mode_)
ager@chromium.org357bf652010-04-12 11:30:10 +0000645 | KnownIntBits::encode(MinorKeyForKnownInt())
646 | TypeInfoBits::encode(runtime_operands_type_)
647 | RegisterBits::encode(lhs_.is(r0));
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000648 }
649
650 void Generate(MacroAssembler* masm);
ager@chromium.org357bf652010-04-12 11:30:10 +0000651 void HandleNonSmiBitwiseOp(MacroAssembler* masm, Register lhs, Register rhs);
652 void HandleBinaryOpSlowCases(MacroAssembler* masm,
653 Label* not_smi,
654 Register lhs,
655 Register rhs,
656 const Builtins::JavaScript& builtin);
657 void GenerateTypeTransition(MacroAssembler* masm);
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000658
659 static bool RhsIsOneWeWantToOptimizeFor(Token::Value op, int constant_rhs) {
660 if (constant_rhs == CodeGenerator::kUnknownIntValue) return false;
661 if (op == Token::DIV) return constant_rhs >= 2 && constant_rhs <= 3;
662 if (op == Token::MOD) {
663 if (constant_rhs <= 1) return false;
664 if (constant_rhs <= 10) return true;
665 if (constant_rhs <= kMaxKnownRhs && IsPowerOf2(constant_rhs)) return true;
666 return false;
667 }
668 return false;
669 }
670
671 int MinorKeyForKnownInt() {
672 if (!specialized_on_rhs_) return 0;
673 if (constant_rhs_ <= 10) return constant_rhs_ + 1;
674 ASSERT(IsPowerOf2(constant_rhs_));
675 int key = 12;
676 int d = constant_rhs_;
677 while ((d & 1) == 0) {
678 key++;
679 d >>= 1;
680 }
ager@chromium.org357bf652010-04-12 11:30:10 +0000681 ASSERT(key >= 0 && key < (1 << kKnownRhsKeyBits));
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000682 return key;
683 }
684
ager@chromium.org357bf652010-04-12 11:30:10 +0000685 int KnownBitsForMinorKey(int key) {
686 if (!key) return 0;
687 if (key <= 11) return key - 1;
688 int d = 1;
689 while (key != 12) {
690 key--;
691 d <<= 1;
692 }
693 return d;
694 }
695
696 Register LhsRegister(bool lhs_is_r0) {
697 return lhs_is_r0 ? r0 : r1;
698 }
699
700 Register RhsRegister(bool lhs_is_r0) {
701 return lhs_is_r0 ? r1 : r0;
702 }
703
704 bool ShouldGenerateSmiCode() {
705 return ((op_ != Token::DIV && op_ != Token::MOD) || specialized_on_rhs_) &&
706 runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS &&
707 runtime_operands_type_ != BinaryOpIC::STRINGS;
708 }
709
710 bool ShouldGenerateFPCode() {
711 return runtime_operands_type_ != BinaryOpIC::STRINGS;
712 }
713
714 virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
715
716 virtual InlineCacheState GetICState() {
717 return BinaryOpIC::ToState(runtime_operands_type_);
718 }
719
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000720 const char* GetName();
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000721
722#ifdef DEBUG
723 void Print() {
724 if (!specialized_on_rhs_) {
725 PrintF("GenericBinaryOpStub (%s)\n", Token::String(op_));
726 } else {
727 PrintF("GenericBinaryOpStub (%s by %d)\n",
728 Token::String(op_),
729 constant_rhs_);
730 }
731 }
732#endif
733};
734
735
ager@chromium.orgac091b72010-05-05 07:34:42 +0000736class StringHelper : public AllStatic {
ager@chromium.org5c838252010-02-19 08:53:10 +0000737 public:
738 // Generate code for copying characters using a simple loop. This should only
739 // be used in places where the number of characters is small and the
740 // additional setup and checking in GenerateCopyCharactersLong adds too much
741 // overhead. 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 GenerateCopyCharacters(MacroAssembler* masm,
744 Register dest,
745 Register src,
746 Register count,
747 Register scratch,
748 bool ascii);
ager@chromium.org5c838252010-02-19 08:53:10 +0000749
750 // Generate code for copying a large number of characters. This function
751 // is allowed to spend extra time setting up conditions to make copying
752 // faster. Copying of overlapping regions is not supported.
753 // Dest register ends at the position after the last character written.
ager@chromium.orgac091b72010-05-05 07:34:42 +0000754 static void GenerateCopyCharactersLong(MacroAssembler* masm,
755 Register dest,
756 Register src,
757 Register count,
758 Register scratch1,
759 Register scratch2,
760 Register scratch3,
761 Register scratch4,
762 Register scratch5,
763 int flags);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000764
765
766 // Probe the symbol table for a two character string. If the string is
767 // not found by probing a jump to the label not_found is performed. This jump
768 // does not guarantee that the string is not in the symbol table. If the
769 // string is found the code falls through with the string in register r0.
770 // Contents of both c1 and c2 registers are modified. At the exit c1 is
771 // guaranteed to contain halfword with low and high bytes equal to
772 // initial contents of c1 and c2 respectively.
ager@chromium.orgac091b72010-05-05 07:34:42 +0000773 static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
774 Register c1,
775 Register c2,
776 Register scratch1,
777 Register scratch2,
778 Register scratch3,
779 Register scratch4,
780 Register scratch5,
781 Label* not_found);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000782
783 // Generate string hash.
ager@chromium.orgac091b72010-05-05 07:34:42 +0000784 static void GenerateHashInit(MacroAssembler* masm,
785 Register hash,
786 Register character);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000787
ager@chromium.orgac091b72010-05-05 07:34:42 +0000788 static void GenerateHashAddCharacter(MacroAssembler* masm,
789 Register hash,
790 Register character);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000791
ager@chromium.orgac091b72010-05-05 07:34:42 +0000792 static void GenerateHashGetHash(MacroAssembler* masm,
793 Register hash);
794
795 private:
796 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
ager@chromium.org5c838252010-02-19 08:53:10 +0000797};
798
799
800// Flag that indicates how to generate code for the stub StringAddStub.
801enum StringAddFlags {
802 NO_STRING_ADD_FLAGS = 0,
803 NO_STRING_CHECK_IN_STUB = 1 << 0 // Omit string check in stub.
804};
805
806
ager@chromium.orgac091b72010-05-05 07:34:42 +0000807class StringAddStub: public CodeStub {
ager@chromium.org5c838252010-02-19 08:53:10 +0000808 public:
809 explicit StringAddStub(StringAddFlags flags) {
810 string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0);
811 }
812
813 private:
814 Major MajorKey() { return StringAdd; }
815 int MinorKey() { return string_check_ ? 0 : 1; }
816
817 void Generate(MacroAssembler* masm);
818
819 // Should the stub check whether arguments are strings?
820 bool string_check_;
821};
822
823
ager@chromium.orgac091b72010-05-05 07:34:42 +0000824class SubStringStub: public CodeStub {
ager@chromium.org5c838252010-02-19 08:53:10 +0000825 public:
826 SubStringStub() {}
827
828 private:
829 Major MajorKey() { return SubString; }
830 int MinorKey() { return 0; }
831
832 void Generate(MacroAssembler* masm);
833};
834
835
836
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000837class StringCompareStub: public CodeStub {
838 public:
839 StringCompareStub() { }
840
841 // Compare two flat ASCII strings and returns result in r0.
842 // Does not use the stack.
843 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
844 Register left,
845 Register right,
846 Register scratch1,
847 Register scratch2,
848 Register scratch3,
849 Register scratch4);
850
851 private:
852 Major MajorKey() { return StringCompare; }
853 int MinorKey() { return 0; }
854
855 void Generate(MacroAssembler* masm);
856};
857
858
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000859// This stub can convert a signed int32 to a heap number (double). It does
860// not work for int32s that are in Smi range! No GC occurs during this stub
861// so you don't have to set up the frame.
862class WriteInt32ToHeapNumberStub : public CodeStub {
863 public:
864 WriteInt32ToHeapNumberStub(Register the_int,
865 Register the_heap_number,
866 Register scratch)
867 : the_int_(the_int),
868 the_heap_number_(the_heap_number),
869 scratch_(scratch) { }
870
871 private:
872 Register the_int_;
873 Register the_heap_number_;
874 Register scratch_;
875
876 // Minor key encoding in 16 bits.
877 class IntRegisterBits: public BitField<int, 0, 4> {};
878 class HeapNumberRegisterBits: public BitField<int, 4, 4> {};
879 class ScratchRegisterBits: public BitField<int, 8, 4> {};
880
881 Major MajorKey() { return WriteInt32ToHeapNumber; }
882 int MinorKey() {
883 // Encode the parameters in a unique 16 bit value.
884 return IntRegisterBits::encode(the_int_.code())
885 | HeapNumberRegisterBits::encode(the_heap_number_.code())
886 | ScratchRegisterBits::encode(scratch_.code());
887 }
888
889 void Generate(MacroAssembler* masm);
890
891 const char* GetName() { return "WriteInt32ToHeapNumberStub"; }
892
893#ifdef DEBUG
894 void Print() { PrintF("WriteInt32ToHeapNumberStub\n"); }
895#endif
896};
897
898
fschneider@chromium.org086aac62010-03-17 13:18:24 +0000899class NumberToStringStub: public CodeStub {
900 public:
901 NumberToStringStub() { }
902
903 // Generate code to do a lookup in the number string cache. If the number in
904 // the register object is found in the cache the generated code falls through
905 // with the result in the result register. The object and the result register
906 // can be the same. If the number is not found in the cache the code jumps to
907 // the label not_found with only the content of register object unchanged.
908 static void GenerateLookupNumberStringCache(MacroAssembler* masm,
909 Register object,
910 Register result,
911 Register scratch1,
912 Register scratch2,
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000913 Register scratch3,
fschneider@chromium.org086aac62010-03-17 13:18:24 +0000914 bool object_is_smi,
915 Label* not_found);
916
917 private:
918 Major MajorKey() { return NumberToString; }
919 int MinorKey() { return 0; }
920
921 void Generate(MacroAssembler* masm);
922
923 const char* GetName() { return "NumberToStringStub"; }
924
925#ifdef DEBUG
926 void Print() {
927 PrintF("NumberToStringStub\n");
928 }
929#endif
930};
931
932
ager@chromium.orgac091b72010-05-05 07:34:42 +0000933class RecordWriteStub : public CodeStub {
934 public:
935 RecordWriteStub(Register object, Register offset, Register scratch)
936 : object_(object), offset_(offset), scratch_(scratch) { }
937
938 void Generate(MacroAssembler* masm);
939
940 private:
941 Register object_;
942 Register offset_;
943 Register scratch_;
944
945#ifdef DEBUG
946 void Print() {
947 PrintF("RecordWriteStub (object reg %d), (offset reg %d),"
948 " (scratch reg %d)\n",
949 object_.code(), offset_.code(), scratch_.code());
950 }
951#endif
952
953 // Minor key encoding in 12 bits. 4 bits for each of the three
954 // registers (object, offset and scratch) OOOOAAAASSSS.
955 class ScratchBits: public BitField<uint32_t, 0, 4> {};
956 class OffsetBits: public BitField<uint32_t, 4, 4> {};
957 class ObjectBits: public BitField<uint32_t, 8, 4> {};
958
959 Major MajorKey() { return RecordWrite; }
960
961 int MinorKey() {
962 // Encode the registers.
963 return ObjectBits::encode(object_.code()) |
964 OffsetBits::encode(offset_.code()) |
965 ScratchBits::encode(scratch_.code());
966 }
967};
968
969
ager@chromium.org7c537e22008-10-16 08:43:32 +0000970} } // namespace v8::internal
971
ager@chromium.org5ec48922009-05-05 07:25:34 +0000972#endif // V8_ARM_CODEGEN_ARM_H_