1 // Copyright 2006-2008 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 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_CODEGEN_H_ 29 #define V8_CODEGEN_H_ 30 31 #include "ast.h" 32 #include "code-stubs.h" 33 #include "runtime.h" 34 35 // Include the declaration of the architecture defined class CodeGenerator. 36 // The contract to the shared code is that the the CodeGenerator is a subclass 37 // of Visitor and that the following methods are available publicly: 38 // MakeCode 39 // SetFunctionInfo 40 // masm 41 // frame 42 // has_valid_frame 43 // SetFrame 44 // DeleteFrame 45 // allocator 46 // AddDeferred 47 // in_spilled_code 48 // set_in_spilled_code 49 // 50 // These methods are either used privately by the shared code or implemented as 51 // shared code: 52 // CodeGenerator 53 // ~CodeGenerator 54 // ProcessDeferred 55 // GenCode 56 // BuildBoilerplate 57 // ComputeCallInitialize 58 // ComputeCallInitializeInLoop 59 // ProcessDeclarations 60 // DeclareGlobals 61 // FindInlineRuntimeLUT 62 // CheckForInlineRuntimeCall 63 // PatchInlineRuntimeEntry 64 // CodeForFunctionPosition 65 // CodeForReturnPosition 66 // CodeForStatementPosition 67 // CodeForSourcePosition 68 69 70 // Mode to overwrite BinaryExpression values. 71 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT }; 72 73 // Types of uncatchable exceptions. 74 enum UncatchableExceptionType { OUT_OF_MEMORY, TERMINATION }; 75 76 77 #if V8_TARGET_ARCH_IA32 78 #include "ia32/codegen-ia32.h" 79 #elif V8_TARGET_ARCH_X64 80 #include "x64/codegen-x64.h" 81 #elif V8_TARGET_ARCH_ARM 82 #include "arm/codegen-arm.h" 83 #else 84 #error Unsupported target architecture. 85 #endif 86 87 #include "register-allocator.h" 88 89 namespace v8 { 90 namespace internal { 91 92 93 // Code generation can be nested. Code generation scopes form a stack 94 // of active code generators. 95 class CodeGeneratorScope BASE_EMBEDDED { 96 public: CodeGeneratorScope(CodeGenerator * cgen)97 explicit CodeGeneratorScope(CodeGenerator* cgen) { 98 previous_ = top_; 99 top_ = cgen; 100 } 101 ~CodeGeneratorScope()102 ~CodeGeneratorScope() { 103 top_ = previous_; 104 } 105 Current()106 static CodeGenerator* Current() { 107 ASSERT(top_ != NULL); 108 return top_; 109 } 110 111 private: 112 static CodeGenerator* top_; 113 CodeGenerator* previous_; 114 }; 115 116 117 // Deferred code objects are small pieces of code that are compiled 118 // out of line. They are used to defer the compilation of uncommon 119 // paths thereby avoiding expensive jumps around uncommon code parts. 120 class DeferredCode: public ZoneObject { 121 public: 122 DeferredCode(); ~DeferredCode()123 virtual ~DeferredCode() { } 124 125 virtual void Generate() = 0; 126 masm()127 MacroAssembler* masm() { return masm_; } 128 statement_position()129 int statement_position() const { return statement_position_; } position()130 int position() const { return position_; } 131 entry_label()132 Label* entry_label() { return &entry_label_; } exit_label()133 Label* exit_label() { return &exit_label_; } 134 135 #ifdef DEBUG set_comment(const char * comment)136 void set_comment(const char* comment) { comment_ = comment; } comment()137 const char* comment() const { return comment_; } 138 #else set_comment(const char * comment)139 void set_comment(const char* comment) { } comment()140 const char* comment() const { return ""; } 141 #endif 142 143 inline void Jump(); 144 inline void Branch(Condition cc); BindExit()145 void BindExit() { masm_->bind(&exit_label_); } 146 147 void SaveRegisters(); 148 void RestoreRegisters(); 149 150 protected: 151 MacroAssembler* masm_; 152 153 private: 154 // Constants indicating special actions. They should not be multiples 155 // of kPointerSize so they will not collide with valid offsets from 156 // the frame pointer. 157 static const int kIgnore = -1; 158 static const int kPush = 1; 159 160 // This flag is ored with a valid offset from the frame pointer, so 161 // it should fit in the low zero bits of a valid offset. 162 static const int kSyncedFlag = 2; 163 164 int statement_position_; 165 int position_; 166 167 Label entry_label_; 168 Label exit_label_; 169 170 int registers_[RegisterAllocator::kNumRegisters]; 171 172 #ifdef DEBUG 173 const char* comment_; 174 #endif 175 DISALLOW_COPY_AND_ASSIGN(DeferredCode); 176 }; 177 178 179 // RuntimeStub models code stubs calling entry points in the Runtime class. 180 class RuntimeStub : public CodeStub { 181 public: RuntimeStub(Runtime::FunctionId id,int num_arguments)182 explicit RuntimeStub(Runtime::FunctionId id, int num_arguments) 183 : id_(id), num_arguments_(num_arguments) { } 184 185 void Generate(MacroAssembler* masm); 186 187 // Disassembler support. It is useful to be able to print the name 188 // of the runtime function called through this stub. GetNameFromMinorKey(int minor_key)189 static const char* GetNameFromMinorKey(int minor_key) { 190 return Runtime::FunctionForId(IdField::decode(minor_key))->stub_name; 191 } 192 193 private: 194 Runtime::FunctionId id_; 195 int num_arguments_; 196 197 class ArgumentField: public BitField<int, 0, 16> {}; 198 class IdField: public BitField<Runtime::FunctionId, 16, kMinorBits - 16> {}; 199 MajorKey()200 Major MajorKey() { return Runtime; } MinorKey()201 int MinorKey() { 202 return IdField::encode(id_) | ArgumentField::encode(num_arguments_); 203 } 204 205 const char* GetName(); 206 207 #ifdef DEBUG Print()208 void Print() { 209 PrintF("RuntimeStub (id %s)\n", Runtime::FunctionForId(id_)->name); 210 } 211 #endif 212 }; 213 214 215 class StackCheckStub : public CodeStub { 216 public: StackCheckStub()217 StackCheckStub() { } 218 219 void Generate(MacroAssembler* masm); 220 221 private: 222 GetName()223 const char* GetName() { return "StackCheckStub"; } 224 MajorKey()225 Major MajorKey() { return StackCheck; } MinorKey()226 int MinorKey() { return 0; } 227 }; 228 229 230 class InstanceofStub: public CodeStub { 231 public: InstanceofStub()232 InstanceofStub() { } 233 234 void Generate(MacroAssembler* masm); 235 236 private: MajorKey()237 Major MajorKey() { return Instanceof; } MinorKey()238 int MinorKey() { return 0; } 239 }; 240 241 242 class UnarySubStub : public CodeStub { 243 public: UnarySubStub(bool overwrite)244 explicit UnarySubStub(bool overwrite) 245 : overwrite_(overwrite) { } 246 247 private: 248 bool overwrite_; MajorKey()249 Major MajorKey() { return UnarySub; } MinorKey()250 int MinorKey() { return overwrite_ ? 1 : 0; } 251 void Generate(MacroAssembler* masm); 252 GetName()253 const char* GetName() { return "UnarySubStub"; } 254 }; 255 256 257 class CompareStub: public CodeStub { 258 public: CompareStub(Condition cc,bool strict)259 CompareStub(Condition cc, bool strict) : cc_(cc), strict_(strict) { } 260 261 void Generate(MacroAssembler* masm); 262 263 private: 264 Condition cc_; 265 bool strict_; 266 MajorKey()267 Major MajorKey() { return Compare; } 268 269 int MinorKey(); 270 271 // Branch to the label if the given object isn't a symbol. 272 void BranchIfNonSymbol(MacroAssembler* masm, 273 Label* label, 274 Register object, 275 Register scratch); 276 277 #ifdef DEBUG Print()278 void Print() { 279 PrintF("CompareStub (cc %d), (strict %s)\n", 280 static_cast<int>(cc_), 281 strict_ ? "true" : "false"); 282 } 283 #endif 284 }; 285 286 287 class CEntryStub : public CodeStub { 288 public: CEntryStub()289 CEntryStub() { } 290 Generate(MacroAssembler * masm)291 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); } 292 293 protected: 294 void GenerateBody(MacroAssembler* masm, bool is_debug_break); 295 void GenerateCore(MacroAssembler* masm, 296 Label* throw_normal_exception, 297 Label* throw_termination_exception, 298 Label* throw_out_of_memory_exception, 299 StackFrame::Type frame_type, 300 bool do_gc, 301 bool always_allocate_scope); 302 void GenerateThrowTOS(MacroAssembler* masm); 303 void GenerateThrowUncatchable(MacroAssembler* masm, 304 UncatchableExceptionType type); 305 306 private: MajorKey()307 Major MajorKey() { return CEntry; } MinorKey()308 int MinorKey() { return 0; } 309 GetName()310 const char* GetName() { return "CEntryStub"; } 311 }; 312 313 314 class CEntryDebugBreakStub : public CEntryStub { 315 public: CEntryDebugBreakStub()316 CEntryDebugBreakStub() { } 317 Generate(MacroAssembler * masm)318 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); } 319 320 private: MinorKey()321 int MinorKey() { return 1; } 322 GetName()323 const char* GetName() { return "CEntryDebugBreakStub"; } 324 }; 325 326 327 class JSEntryStub : public CodeStub { 328 public: JSEntryStub()329 JSEntryStub() { } 330 Generate(MacroAssembler * masm)331 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); } 332 333 protected: 334 void GenerateBody(MacroAssembler* masm, bool is_construct); 335 336 private: MajorKey()337 Major MajorKey() { return JSEntry; } MinorKey()338 int MinorKey() { return 0; } 339 GetName()340 const char* GetName() { return "JSEntryStub"; } 341 }; 342 343 344 class JSConstructEntryStub : public JSEntryStub { 345 public: JSConstructEntryStub()346 JSConstructEntryStub() { } 347 Generate(MacroAssembler * masm)348 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); } 349 350 private: MinorKey()351 int MinorKey() { return 1; } 352 GetName()353 const char* GetName() { return "JSConstructEntryStub"; } 354 }; 355 356 357 class ArgumentsAccessStub: public CodeStub { 358 public: 359 enum Type { 360 READ_LENGTH, 361 READ_ELEMENT, 362 NEW_OBJECT 363 }; 364 ArgumentsAccessStub(Type type)365 explicit ArgumentsAccessStub(Type type) : type_(type) { } 366 367 private: 368 Type type_; 369 MajorKey()370 Major MajorKey() { return ArgumentsAccess; } MinorKey()371 int MinorKey() { return type_; } 372 373 void Generate(MacroAssembler* masm); 374 void GenerateReadLength(MacroAssembler* masm); 375 void GenerateReadElement(MacroAssembler* masm); 376 void GenerateNewObject(MacroAssembler* masm); 377 GetName()378 const char* GetName() { return "ArgumentsAccessStub"; } 379 380 #ifdef DEBUG Print()381 void Print() { 382 PrintF("ArgumentsAccessStub (type %d)\n", type_); 383 } 384 #endif 385 }; 386 387 388 } // namespace internal 389 } // namespace v8 390 391 #endif // V8_CODEGEN_H_ 392