1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
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.
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.
28 #ifndef V8_ARM_CODEGEN_ARM_H_
29 #define V8_ARM_CODEGEN_ARM_H_
36 // Forward declarations
37 class CompilationInfo;
39 class RegisterAllocator;
42 enum InitState { CONST_INIT, NOT_CONST_INIT };
43 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
46 // -------------------------------------------------------------------------
49 // A reference is a C++ stack-allocated object that puts a
50 // reference on the virtual frame. The reference may be consumed
51 // by GetValue, TakeValue, SetValue, and Codegen::UnloadReference.
52 // When the lifetime (scope) of a valid reference ends, it must have
53 // been consumed, and be in state UNLOADED.
54 class Reference BASE_EMBEDDED {
56 // The values of the types is important, see size().
57 enum Type { UNLOADED = -2, ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
58 Reference(CodeGenerator* cgen,
59 Expression* expression,
60 bool persist_after_get = false);
63 Expression* expression() const { return expression_; }
64 Type type() const { return type_; }
65 void set_type(Type value) {
66 ASSERT_EQ(ILLEGAL, type_);
71 ASSERT_NE(ILLEGAL, type_);
72 ASSERT_NE(UNLOADED, type_);
75 // The size the reference takes up on the stack.
77 return (type_ < SLOT) ? 0 : type_;
80 bool is_illegal() const { return type_ == ILLEGAL; }
81 bool is_slot() const { return type_ == SLOT; }
82 bool is_property() const { return type_ == NAMED || type_ == KEYED; }
83 bool is_unloaded() const { return type_ == UNLOADED; }
85 // Return the name. Only valid for named property references.
86 Handle<String> GetName();
88 // Generate code to push the value of the reference on top of the
89 // expression stack. The reference is expected to be already on top of
90 // the expression stack, and it is consumed by the call unless the
91 // reference is for a compound assignment.
92 // If the reference is not consumed, it is left in place under its value.
95 // Generate code to pop a reference, push the value of the reference,
96 // and then spill the stack frame.
97 inline void GetValueAndSpill();
99 // Generate code to store the value on top of the expression stack in the
100 // reference. The reference is expected to be immediately below the value
101 // on the expression stack. The value is stored in the location specified
102 // by the reference, and is left on top of the stack, after the reference
103 // is popped from beneath it (unloaded).
104 void SetValue(InitState init_state);
107 CodeGenerator* cgen_;
108 Expression* expression_;
110 // Keep the reference on the stack after get, so it can be used by set later.
111 bool persist_after_get_;
115 // -------------------------------------------------------------------------
116 // Code generation state
118 // The state is passed down the AST by the code generator (and back up, in
119 // the form of the state of the label pair). It is threaded through the
120 // call stack. Constructing a state implicitly pushes it on the owning code
121 // generator's stack of states, and destroying one implicitly pops it.
123 class CodeGenState BASE_EMBEDDED {
125 // Create an initial code generator state. Destroying the initial state
126 // leaves the code generator with a NULL state.
127 explicit CodeGenState(CodeGenerator* owner);
129 // Create a code generator state based on a code generator's current
130 // state. The new state has its own pair of branch labels.
131 CodeGenState(CodeGenerator* owner,
132 JumpTarget* true_target,
133 JumpTarget* false_target);
135 // Destroy a code generator state and restore the owning code generator's
139 JumpTarget* true_target() const { return true_target_; }
140 JumpTarget* false_target() const { return false_target_; }
143 CodeGenerator* owner_;
144 JumpTarget* true_target_;
145 JumpTarget* false_target_;
146 CodeGenState* previous_;
150 // -------------------------------------------------------------------------
153 class CodeGenerator: public AstVisitor {
155 // Takes a function literal, generates code for it. This function should only
156 // be called by compiler.cc.
157 static Handle<Code> MakeCode(CompilationInfo* info);
159 // Printing of AST, etc. as requested by flags.
160 static void MakeCodePrologue(CompilationInfo* info);
162 // Allocate and install the code.
163 static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
165 CompilationInfo* info);
167 #ifdef ENABLE_LOGGING_AND_PROFILING
168 static bool ShouldGenerateLog(Expression* type);
171 static void SetFunctionInfo(Handle<JSFunction> fun,
172 FunctionLiteral* lit,
174 Handle<Script> script);
176 static void RecordPositions(MacroAssembler* masm, int pos);
179 MacroAssembler* masm() { return masm_; }
180 VirtualFrame* frame() const { return frame_; }
181 inline Handle<Script> script();
183 bool has_valid_frame() const { return frame_ != NULL; }
185 // Set the virtual frame to be new_frame, with non-frame register
186 // reference counts given by non_frame_registers. The non-frame
187 // register reference counts of the old frame are returned in
188 // non_frame_registers.
189 void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers);
193 RegisterAllocator* allocator() const { return allocator_; }
195 CodeGenState* state() { return state_; }
196 void set_state(CodeGenState* state) { state_ = state; }
198 void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
200 static const int kUnknownIntValue = -1;
202 // If the name is an inline runtime function call return the number of
203 // expected arguments. Otherwise return -1.
204 static int InlineRuntimeCallArgumentsCount(Handle<String> name);
207 // Construction/Destruction
208 explicit CodeGenerator(MacroAssembler* masm);
211 inline bool is_eval();
212 inline Scope* scope();
214 // Generating deferred code.
215 void ProcessDeferred();
218 bool has_cc() const { return cc_reg_ != al; }
219 JumpTarget* true_target() const { return state_->true_target(); }
220 JumpTarget* false_target() const { return state_->false_target(); }
222 // We don't track loop nesting level on ARM yet.
223 int loop_nesting() const { return 0; }
226 void VisitStatements(ZoneList<Statement*>* statements);
228 #define DEF_VISIT(type) \
229 void Visit##type(type* node);
230 AST_NODE_LIST(DEF_VISIT)
233 // Visit a statement and then spill the virtual frame if control flow can
234 // reach the end of the statement (ie, it does not exit via break,
235 // continue, return, or throw). This function is used temporarily while
236 // the code generator is being transformed.
237 inline void VisitAndSpill(Statement* statement);
239 // Visit a list of statements and then spill the virtual frame if control
240 // flow can reach the end of the list.
241 inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
243 // Main code generation function
244 void Generate(CompilationInfo* info);
246 // The following are used by class Reference.
247 void LoadReference(Reference* ref);
248 void UnloadReference(Reference* ref);
250 static MemOperand ContextOperand(Register context, int index) {
251 return MemOperand(context, Context::SlotOffset(index));
254 MemOperand SlotOperand(Slot* slot, Register tmp);
256 MemOperand ContextSlotOperandCheckExtensions(Slot* slot,
262 static MemOperand GlobalObject() {
263 return ContextOperand(cp, Context::GLOBAL_INDEX);
266 void LoadCondition(Expression* x,
267 JumpTarget* true_target,
268 JumpTarget* false_target,
270 void Load(Expression* expr);
272 void LoadGlobalReceiver(Register scratch);
274 // Generate code to push the value of an expression on top of the frame
275 // and then spill the frame fully to memory. This function is used
276 // temporarily while the code generator is being transformed.
277 inline void LoadAndSpill(Expression* expression);
279 // Call LoadCondition and then spill the virtual frame unless control flow
280 // cannot reach the end of the expression (ie, by emitting only
281 // unconditional jumps to the control targets).
282 inline void LoadConditionAndSpill(Expression* expression,
283 JumpTarget* true_target,
284 JumpTarget* false_target,
287 // Read a value from a slot and leave it on top of the expression stack.
288 void LoadFromSlot(Slot* slot, TypeofState typeof_state);
289 // Store the value on top of the stack to a slot.
290 void StoreToSlot(Slot* slot, InitState init_state);
291 // Load a keyed property, leaving it in r0. The receiver and key are
292 // passed on the stack, and remain there.
293 void EmitKeyedLoad(bool is_global);
295 void LoadFromGlobalSlotCheckExtensions(Slot* slot,
296 TypeofState typeof_state,
301 // Special code for typeof expressions: Unfortunately, we must
302 // be careful when loading the expression in 'typeof'
303 // expressions. We are not allowed to throw reference errors for
304 // non-existing properties of the global object, so we must make it
305 // look like an explicit property access, instead of an access
306 // through the context chain.
307 void LoadTypeofExpression(Expression* x);
309 void ToBoolean(JumpTarget* true_target, JumpTarget* false_target);
311 // Generate code that computes a shortcutting logical operation.
312 void GenerateLogicalBooleanOperation(BinaryOperation* node);
314 void GenericBinaryOperation(Token::Value op,
315 OverwriteMode overwrite_mode,
316 int known_rhs = kUnknownIntValue);
317 void Comparison(Condition cc,
320 bool strict = false);
322 void SmiOperation(Token::Value op,
323 Handle<Object> value,
327 void CallWithArguments(ZoneList<Expression*>* arguments,
328 CallFunctionFlags flags,
332 void Branch(bool if_true, JumpTarget* target);
335 struct InlineRuntimeLUT {
336 void (CodeGenerator::*method)(ZoneList<Expression*>*);
341 static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
342 bool CheckForInlineRuntimeCall(CallRuntime* node);
343 static bool PatchInlineRuntimeEntry(Handle<String> name,
344 const InlineRuntimeLUT& new_entry,
345 InlineRuntimeLUT* old_entry);
347 static Handle<Code> ComputeLazyCompile(int argc);
348 void ProcessDeclarations(ZoneList<Declaration*>* declarations);
350 static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
352 // Declare global variables and functions in the given array of
354 void DeclareGlobals(Handle<FixedArray> pairs);
356 // Instantiate the function based on the shared function info.
357 void InstantiateFunction(Handle<SharedFunctionInfo> function_info);
359 // Support for type checks.
360 void GenerateIsSmi(ZoneList<Expression*>* args);
361 void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
362 void GenerateIsArray(ZoneList<Expression*>* args);
363 void GenerateIsRegExp(ZoneList<Expression*>* args);
364 void GenerateIsObject(ZoneList<Expression*>* args);
365 void GenerateIsFunction(ZoneList<Expression*>* args);
366 void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
368 // Support for construct call checks.
369 void GenerateIsConstructCall(ZoneList<Expression*>* args);
371 // Support for arguments.length and arguments[?].
372 void GenerateArgumentsLength(ZoneList<Expression*>* args);
373 void GenerateArguments(ZoneList<Expression*>* args);
375 // Support for accessing the class and value fields of an object.
376 void GenerateClassOf(ZoneList<Expression*>* args);
377 void GenerateValueOf(ZoneList<Expression*>* args);
378 void GenerateSetValueOf(ZoneList<Expression*>* args);
380 // Fast support for charCodeAt(n).
381 void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
383 // Fast support for string.charAt(n) and string[n].
384 void GenerateCharFromCode(ZoneList<Expression*>* args);
386 // Fast support for object equality testing.
387 void GenerateObjectEquals(ZoneList<Expression*>* args);
389 void GenerateLog(ZoneList<Expression*>* args);
391 // Fast support for Math.random().
392 void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
394 // Fast support for StringAdd.
395 void GenerateStringAdd(ZoneList<Expression*>* args);
397 // Fast support for SubString.
398 void GenerateSubString(ZoneList<Expression*>* args);
400 // Fast support for StringCompare.
401 void GenerateStringCompare(ZoneList<Expression*>* args);
403 // Support for direct calls from JavaScript to native RegExp code.
404 void GenerateRegExpExec(ZoneList<Expression*>* args);
406 // Fast support for number to string.
407 void GenerateNumberToString(ZoneList<Expression*>* args);
409 // Fast call to math functions.
410 void GenerateMathPow(ZoneList<Expression*>* args);
411 void GenerateMathSin(ZoneList<Expression*>* args);
412 void GenerateMathCos(ZoneList<Expression*>* args);
413 void GenerateMathSqrt(ZoneList<Expression*>* args);
415 // Simple condition analysis.
416 enum ConditionAnalysis {
421 ConditionAnalysis AnalyzeCondition(Expression* cond);
423 // Methods used to indicate which source code is generated for. Source
424 // positions are collected by the assembler and emitted with the relocation
426 void CodeForFunctionPosition(FunctionLiteral* fun);
427 void CodeForReturnPosition(FunctionLiteral* fun);
428 void CodeForStatementPosition(Statement* node);
429 void CodeForDoWhileConditionPosition(DoWhileStatement* stmt);
430 void CodeForSourcePosition(int pos);
433 // True if the registers are valid for entry to a block.
434 bool HasValidEntryRegisters();
437 List<DeferredCode*> deferred_;
440 MacroAssembler* masm_; // to generate code
442 CompilationInfo* info_;
444 // Code generation state
445 VirtualFrame* frame_;
446 RegisterAllocator* allocator_;
448 CodeGenState* state_;
451 BreakTarget function_return_;
453 // True if the function return is shadowed (ie, jumping to the target
454 // function_return_ does not jump to the true function return, but rather
455 // to some unlinking code).
456 bool function_return_is_shadowed_;
458 static InlineRuntimeLUT kInlineRuntimeLUT[];
460 friend class VirtualFrame;
461 friend class JumpTarget;
462 friend class Reference;
463 friend class FastCodeGenerator;
464 friend class FullCodeGenerator;
465 friend class FullCodeGenSyntaxChecker;
467 DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
471 class GenericBinaryOpStub : public CodeStub {
473 GenericBinaryOpStub(Token::Value op,
475 int constant_rhs = CodeGenerator::kUnknownIntValue)
478 constant_rhs_(constant_rhs),
479 specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op, constant_rhs)),
480 runtime_operands_type_(BinaryOpIC::DEFAULT),
483 GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info)
484 : op_(OpBits::decode(key)),
485 mode_(ModeBits::decode(key)),
486 constant_rhs_(KnownBitsForMinorKey(KnownIntBits::decode(key))),
487 specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op_, constant_rhs_)),
488 runtime_operands_type_(type_info),
495 bool specialized_on_rhs_;
496 BinaryOpIC::TypeInfo runtime_operands_type_;
499 static const int kMaxKnownRhs = 0x40000000;
501 // Minor key encoding in 18 bits.
502 class ModeBits: public BitField<OverwriteMode, 0, 2> {};
503 class OpBits: public BitField<Token::Value, 2, 6> {};
504 class KnownIntBits: public BitField<int, 8, 8> {};
505 class TypeInfoBits: public BitField<int, 16, 2> {};
507 Major MajorKey() { return GenericBinaryOp; }
509 // Encode the parameters in a unique 18 bit value.
510 return OpBits::encode(op_)
511 | ModeBits::encode(mode_)
512 | KnownIntBits::encode(MinorKeyForKnownInt())
513 | TypeInfoBits::encode(runtime_operands_type_);
516 void Generate(MacroAssembler* masm);
517 void HandleNonSmiBitwiseOp(MacroAssembler* masm);
518 void HandleBinaryOpSlowCases(MacroAssembler* masm,
520 const Builtins::JavaScript& builtin);
521 void GenerateTypeTransition(MacroAssembler* masm);
523 static bool RhsIsOneWeWantToOptimizeFor(Token::Value op, int constant_rhs) {
524 if (constant_rhs == CodeGenerator::kUnknownIntValue) return false;
525 if (op == Token::DIV) return constant_rhs >= 2 && constant_rhs <= 3;
526 if (op == Token::MOD) {
527 if (constant_rhs <= 1) return false;
528 if (constant_rhs <= 10) return true;
529 if (constant_rhs <= kMaxKnownRhs && IsPowerOf2(constant_rhs)) return true;
535 int MinorKeyForKnownInt() {
536 if (!specialized_on_rhs_) return 0;
537 if (constant_rhs_ <= 10) return constant_rhs_ + 1;
538 ASSERT(IsPowerOf2(constant_rhs_));
540 int d = constant_rhs_;
541 while ((d & 1) == 0) {
548 int KnownBitsForMinorKey(int key) {
550 if (key <= 11) return key - 1;
559 bool ShouldGenerateSmiCode() {
560 return ((op_ != Token::DIV && op_ != Token::MOD) || specialized_on_rhs_) &&
561 runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS &&
562 runtime_operands_type_ != BinaryOpIC::STRINGS;
565 bool ShouldGenerateFPCode() {
566 return runtime_operands_type_ != BinaryOpIC::STRINGS;
569 virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
571 virtual InlineCacheState GetICState() {
572 return BinaryOpIC::ToState(runtime_operands_type_);
575 const char* GetName();
579 if (!specialized_on_rhs_) {
580 PrintF("GenericBinaryOpStub (%s)\n", Token::String(op_));
582 PrintF("GenericBinaryOpStub (%s by %d)\n",
591 class StringStubBase: public CodeStub {
593 // Generate code for copying characters using a simple loop. This should only
594 // be used in places where the number of characters is small and the
595 // additional setup and checking in GenerateCopyCharactersLong adds too much
596 // overhead. Copying of overlapping regions is not supported.
597 // Dest register ends at the position after the last character written.
598 void GenerateCopyCharacters(MacroAssembler* masm,
605 // Generate code for copying a large number of characters. This function
606 // is allowed to spend extra time setting up conditions to make copying
607 // faster. Copying of overlapping regions is not supported.
608 // Dest register ends at the position after the last character written.
609 void GenerateCopyCharactersLong(MacroAssembler* masm,
621 // Probe the symbol table for a two character string. If the string is
622 // not found by probing a jump to the label not_found is performed. This jump
623 // does not guarantee that the string is not in the symbol table. If the
624 // string is found the code falls through with the string in register r0.
625 // Contents of both c1 and c2 registers are modified. At the exit c1 is
626 // guaranteed to contain halfword with low and high bytes equal to
627 // initial contents of c1 and c2 respectively.
628 void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
638 // Generate string hash.
639 void GenerateHashInit(MacroAssembler* masm,
643 void GenerateHashAddCharacter(MacroAssembler* masm,
647 void GenerateHashGetHash(MacroAssembler* masm,
652 // Flag that indicates how to generate code for the stub StringAddStub.
653 enum StringAddFlags {
654 NO_STRING_ADD_FLAGS = 0,
655 NO_STRING_CHECK_IN_STUB = 1 << 0 // Omit string check in stub.
659 class StringAddStub: public StringStubBase {
661 explicit StringAddStub(StringAddFlags flags) {
662 string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0);
666 Major MajorKey() { return StringAdd; }
667 int MinorKey() { return string_check_ ? 0 : 1; }
669 void Generate(MacroAssembler* masm);
671 // Should the stub check whether arguments are strings?
676 class SubStringStub: public StringStubBase {
681 Major MajorKey() { return SubString; }
682 int MinorKey() { return 0; }
684 void Generate(MacroAssembler* masm);
689 class StringCompareStub: public CodeStub {
691 StringCompareStub() { }
693 // Compare two flat ASCII strings and returns result in r0.
694 // Does not use the stack.
695 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
704 Major MajorKey() { return StringCompare; }
705 int MinorKey() { return 0; }
707 void Generate(MacroAssembler* masm);
711 // This stub can convert a signed int32 to a heap number (double). It does
712 // not work for int32s that are in Smi range! No GC occurs during this stub
713 // so you don't have to set up the frame.
714 class WriteInt32ToHeapNumberStub : public CodeStub {
716 WriteInt32ToHeapNumberStub(Register the_int,
717 Register the_heap_number,
720 the_heap_number_(the_heap_number),
721 scratch_(scratch) { }
725 Register the_heap_number_;
728 // Minor key encoding in 16 bits.
729 class IntRegisterBits: public BitField<int, 0, 4> {};
730 class HeapNumberRegisterBits: public BitField<int, 4, 4> {};
731 class ScratchRegisterBits: public BitField<int, 8, 4> {};
733 Major MajorKey() { return WriteInt32ToHeapNumber; }
735 // Encode the parameters in a unique 16 bit value.
736 return IntRegisterBits::encode(the_int_.code())
737 | HeapNumberRegisterBits::encode(the_heap_number_.code())
738 | ScratchRegisterBits::encode(scratch_.code());
741 void Generate(MacroAssembler* masm);
743 const char* GetName() { return "WriteInt32ToHeapNumberStub"; }
746 void Print() { PrintF("WriteInt32ToHeapNumberStub\n"); }
751 class NumberToStringStub: public CodeStub {
753 NumberToStringStub() { }
755 // Generate code to do a lookup in the number string cache. If the number in
756 // the register object is found in the cache the generated code falls through
757 // with the result in the result register. The object and the result register
758 // can be the same. If the number is not found in the cache the code jumps to
759 // the label not_found with only the content of register object unchanged.
760 static void GenerateLookupNumberStringCache(MacroAssembler* masm,
769 Major MajorKey() { return NumberToString; }
770 int MinorKey() { return 0; }
772 void Generate(MacroAssembler* masm);
774 const char* GetName() { return "NumberToStringStub"; }
778 PrintF("NumberToStringStub\n");
784 } } // namespace v8::internal
786 #endif // V8_ARM_CODEGEN_ARM_H_