codegen.h revision d0582a6c46733687d045e4188a1bcd0123c758a1
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// MakeCodePrologue 40// MakeCodeEpilogue 41// masm 42// frame 43// script 44// has_valid_frame 45// SetFrame 46// DeleteFrame 47// allocator 48// AddDeferred 49// in_spilled_code 50// set_in_spilled_code 51// RecordPositions 52// 53// These methods are either used privately by the shared code or implemented as 54// shared code: 55// CodeGenerator 56// ~CodeGenerator 57// ProcessDeferred 58// GenCode 59// ComputeLazyCompile 60// BuildBoilerplate 61// ComputeCallInitialize 62// ComputeCallInitializeInLoop 63// ProcessDeclarations 64// DeclareGlobals 65// FindInlineRuntimeLUT 66// CheckForInlineRuntimeCall 67// PatchInlineRuntimeEntry 68// AnalyzeCondition 69// CodeForFunctionPosition 70// CodeForReturnPosition 71// CodeForStatementPosition 72// CodeForDoWhileConditionPosition 73// CodeForSourcePosition 74 75 76// Mode to overwrite BinaryExpression values. 77enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT }; 78 79// Types of uncatchable exceptions. 80enum UncatchableExceptionType { OUT_OF_MEMORY, TERMINATION }; 81 82 83#if V8_TARGET_ARCH_IA32 84#include "ia32/codegen-ia32.h" 85#elif V8_TARGET_ARCH_X64 86#include "x64/codegen-x64.h" 87#elif V8_TARGET_ARCH_ARM 88#include "arm/codegen-arm.h" 89#else 90#error Unsupported target architecture. 91#endif 92 93#include "register-allocator.h" 94 95namespace v8 { 96namespace internal { 97 98 99// Code generation can be nested. Code generation scopes form a stack 100// of active code generators. 101class CodeGeneratorScope BASE_EMBEDDED { 102 public: 103 explicit CodeGeneratorScope(CodeGenerator* cgen) { 104 previous_ = top_; 105 top_ = cgen; 106 } 107 108 ~CodeGeneratorScope() { 109 top_ = previous_; 110 } 111 112 static CodeGenerator* Current() { 113 ASSERT(top_ != NULL); 114 return top_; 115 } 116 117 private: 118 static CodeGenerator* top_; 119 CodeGenerator* previous_; 120}; 121 122 123// Deferred code objects are small pieces of code that are compiled 124// out of line. They are used to defer the compilation of uncommon 125// paths thereby avoiding expensive jumps around uncommon code parts. 126class DeferredCode: public ZoneObject { 127 public: 128 DeferredCode(); 129 virtual ~DeferredCode() { } 130 131 virtual void Generate() = 0; 132 133 MacroAssembler* masm() { return masm_; } 134 135 int statement_position() const { return statement_position_; } 136 int position() const { return position_; } 137 138 Label* entry_label() { return &entry_label_; } 139 Label* exit_label() { return &exit_label_; } 140 141#ifdef DEBUG 142 void set_comment(const char* comment) { comment_ = comment; } 143 const char* comment() const { return comment_; } 144#else 145 void set_comment(const char* comment) { } 146 const char* comment() const { return ""; } 147#endif 148 149 inline void Jump(); 150 inline void Branch(Condition cc); 151 void BindExit() { masm_->bind(&exit_label_); } 152 153 void SaveRegisters(); 154 void RestoreRegisters(); 155 156 protected: 157 MacroAssembler* masm_; 158 159 private: 160 // Constants indicating special actions. They should not be multiples 161 // of kPointerSize so they will not collide with valid offsets from 162 // the frame pointer. 163 static const int kIgnore = -1; 164 static const int kPush = 1; 165 166 // This flag is ored with a valid offset from the frame pointer, so 167 // it should fit in the low zero bits of a valid offset. 168 static const int kSyncedFlag = 2; 169 170 int statement_position_; 171 int position_; 172 173 Label entry_label_; 174 Label exit_label_; 175 176 int registers_[RegisterAllocator::kNumRegisters]; 177 178#ifdef DEBUG 179 const char* comment_; 180#endif 181 DISALLOW_COPY_AND_ASSIGN(DeferredCode); 182}; 183 184 185// RuntimeStub models code stubs calling entry points in the Runtime class. 186class RuntimeStub : public CodeStub { 187 public: 188 explicit RuntimeStub(Runtime::FunctionId id, int num_arguments) 189 : id_(id), num_arguments_(num_arguments) { } 190 191 void Generate(MacroAssembler* masm); 192 193 // Disassembler support. It is useful to be able to print the name 194 // of the runtime function called through this stub. 195 static const char* GetNameFromMinorKey(int minor_key) { 196 return Runtime::FunctionForId(IdField::decode(minor_key))->stub_name; 197 } 198 199 private: 200 Runtime::FunctionId id_; 201 int num_arguments_; 202 203 class ArgumentField: public BitField<int, 0, 16> {}; 204 class IdField: public BitField<Runtime::FunctionId, 16, kMinorBits - 16> {}; 205 206 Major MajorKey() { return Runtime; } 207 int MinorKey() { 208 return IdField::encode(id_) | ArgumentField::encode(num_arguments_); 209 } 210 211 const char* GetName(); 212 213#ifdef DEBUG 214 void Print() { 215 PrintF("RuntimeStub (id %s)\n", Runtime::FunctionForId(id_)->name); 216 } 217#endif 218}; 219 220 221class StackCheckStub : public CodeStub { 222 public: 223 StackCheckStub() { } 224 225 void Generate(MacroAssembler* masm); 226 227 private: 228 229 const char* GetName() { return "StackCheckStub"; } 230 231 Major MajorKey() { return StackCheck; } 232 int MinorKey() { return 0; } 233}; 234 235 236class InstanceofStub: public CodeStub { 237 public: 238 InstanceofStub() { } 239 240 void Generate(MacroAssembler* masm); 241 242 private: 243 Major MajorKey() { return Instanceof; } 244 int MinorKey() { return 0; } 245}; 246 247 248class UnarySubStub : public CodeStub { 249 public: 250 explicit UnarySubStub(bool overwrite) 251 : overwrite_(overwrite) { } 252 253 private: 254 bool overwrite_; 255 Major MajorKey() { return UnarySub; } 256 int MinorKey() { return overwrite_ ? 1 : 0; } 257 void Generate(MacroAssembler* masm); 258 259 const char* GetName() { return "UnarySubStub"; } 260}; 261 262 263class CompareStub: public CodeStub { 264 public: 265 CompareStub(Condition cc, bool strict) : cc_(cc), strict_(strict) { } 266 267 void Generate(MacroAssembler* masm); 268 269 private: 270 Condition cc_; 271 bool strict_; 272 273 Major MajorKey() { return Compare; } 274 275 int MinorKey(); 276 277 // Branch to the label if the given object isn't a symbol. 278 void BranchIfNonSymbol(MacroAssembler* masm, 279 Label* label, 280 Register object, 281 Register scratch); 282 283#ifdef DEBUG 284 void Print() { 285 PrintF("CompareStub (cc %d), (strict %s)\n", 286 static_cast<int>(cc_), 287 strict_ ? "true" : "false"); 288 } 289#endif 290}; 291 292 293class CEntryStub : public CodeStub { 294 public: 295 explicit CEntryStub(int result_size) : result_size_(result_size) { } 296 297 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); } 298 299 protected: 300 void GenerateBody(MacroAssembler* masm, bool is_debug_break); 301 void GenerateCore(MacroAssembler* masm, 302 Label* throw_normal_exception, 303 Label* throw_termination_exception, 304 Label* throw_out_of_memory_exception, 305 ExitFrame::Mode mode, 306 bool do_gc, 307 bool always_allocate_scope); 308 void GenerateThrowTOS(MacroAssembler* masm); 309 void GenerateThrowUncatchable(MacroAssembler* masm, 310 UncatchableExceptionType type); 311 private: 312 // Number of pointers/values returned. 313 int result_size_; 314 315 Major MajorKey() { return CEntry; } 316 // Minor key must differ if different result_size_ values means different 317 // code is generated. 318 int MinorKey(); 319 320 const char* GetName() { return "CEntryStub"; } 321}; 322 323 324class ApiGetterEntryStub : public CodeStub { 325 public: 326 ApiGetterEntryStub(Handle<AccessorInfo> info, 327 ApiFunction* fun) 328 : info_(info), 329 fun_(fun) { } 330 void Generate(MacroAssembler* masm); 331 virtual bool has_custom_cache() { return true; } 332 virtual bool GetCustomCache(Code** code_out); 333 virtual void SetCustomCache(Code* value); 334 335 static const int kStackSpace = 6; 336 static const int kArgc = 4; 337 private: 338 Handle<AccessorInfo> info() { return info_; } 339 ApiFunction* fun() { return fun_; } 340 Major MajorKey() { return NoCache; } 341 int MinorKey() { return 0; } 342 const char* GetName() { return "ApiEntryStub"; } 343 // The accessor info associated with the function. 344 Handle<AccessorInfo> info_; 345 // The function to be called. 346 ApiFunction* fun_; 347}; 348 349 350class CEntryDebugBreakStub : public CEntryStub { 351 public: 352 CEntryDebugBreakStub() : CEntryStub(1) { } 353 354 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); } 355 356 private: 357 int MinorKey() { return 1; } 358 359 const char* GetName() { return "CEntryDebugBreakStub"; } 360}; 361 362 363class JSEntryStub : public CodeStub { 364 public: 365 JSEntryStub() { } 366 367 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); } 368 369 protected: 370 void GenerateBody(MacroAssembler* masm, bool is_construct); 371 372 private: 373 Major MajorKey() { return JSEntry; } 374 int MinorKey() { return 0; } 375 376 const char* GetName() { return "JSEntryStub"; } 377}; 378 379 380class JSConstructEntryStub : public JSEntryStub { 381 public: 382 JSConstructEntryStub() { } 383 384 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); } 385 386 private: 387 int MinorKey() { return 1; } 388 389 const char* GetName() { return "JSConstructEntryStub"; } 390}; 391 392 393class ArgumentsAccessStub: public CodeStub { 394 public: 395 enum Type { 396 READ_LENGTH, 397 READ_ELEMENT, 398 NEW_OBJECT 399 }; 400 401 explicit ArgumentsAccessStub(Type type) : type_(type) { } 402 403 private: 404 Type type_; 405 406 Major MajorKey() { return ArgumentsAccess; } 407 int MinorKey() { return type_; } 408 409 void Generate(MacroAssembler* masm); 410 void GenerateReadLength(MacroAssembler* masm); 411 void GenerateReadElement(MacroAssembler* masm); 412 void GenerateNewObject(MacroAssembler* masm); 413 414 const char* GetName() { return "ArgumentsAccessStub"; } 415 416#ifdef DEBUG 417 void Print() { 418 PrintF("ArgumentsAccessStub (type %d)\n", type_); 419 } 420#endif 421}; 422 423 424} // namespace internal 425} // namespace v8 426 427#endif // V8_CODEGEN_H_ 428