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 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_IA32_CODEGEN_IA32_H_ 29 #define V8_IA32_CODEGEN_IA32_H_ 30 31 namespace v8 { 32 namespace internal { 33 34 // Forward declarations 35 class CompilationInfo; 36 class DeferredCode; 37 class RegisterAllocator; 38 class RegisterFile; 39 40 enum InitState { CONST_INIT, NOT_CONST_INIT }; 41 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; 42 43 44 // ------------------------------------------------------------------------- 45 // Reference support 46 47 // A reference is a C++ stack-allocated object that puts a 48 // reference on the virtual frame. The reference may be consumed 49 // by GetValue, TakeValue, SetValue, and Codegen::UnloadReference. 50 // When the lifetime (scope) of a valid reference ends, it must have 51 // been consumed, and be in state UNLOADED. 52 class Reference BASE_EMBEDDED { 53 public: 54 // The values of the types is important, see size(). 55 enum Type { UNLOADED = -2, ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 }; 56 Reference(CodeGenerator* cgen, 57 Expression* expression, 58 bool persist_after_get = false); 59 ~Reference(); 60 61 Expression* expression() const { return expression_; } 62 Type type() const { return type_; } 63 void set_type(Type value) { 64 ASSERT_EQ(ILLEGAL, type_); 65 type_ = value; 66 } 67 68 void set_unloaded() { 69 ASSERT_NE(ILLEGAL, type_); 70 ASSERT_NE(UNLOADED, type_); 71 type_ = UNLOADED; 72 } 73 // The size the reference takes up on the stack. 74 int size() const { 75 return (type_ < SLOT) ? 0 : type_; 76 } 77 78 bool is_illegal() const { return type_ == ILLEGAL; } 79 bool is_slot() const { return type_ == SLOT; } 80 bool is_property() const { return type_ == NAMED || type_ == KEYED; } 81 bool is_unloaded() const { return type_ == UNLOADED; } 82 83 // Return the name. Only valid for named property references. 84 Handle<String> GetName(); 85 86 // Generate code to push the value of the reference on top of the 87 // expression stack. The reference is expected to be already on top of 88 // the expression stack, and it is consumed by the call unless the 89 // reference is for a compound assignment. 90 // If the reference is not consumed, it is left in place under its value. 91 void GetValue(); 92 93 // Like GetValue except that the slot is expected to be written to before 94 // being read from again. The value of the reference may be invalidated, 95 // causing subsequent attempts to read it to fail. 96 void TakeValue(); 97 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 100 // 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). 103 void SetValue(InitState init_state); 104 105 private: 106 CodeGenerator* cgen_; 107 Expression* expression_; 108 Type type_; 109 // Keep the reference on the stack after get, so it can be used by set later. 110 bool persist_after_get_; 111 }; 112 113 114 // ------------------------------------------------------------------------- 115 // Control destinations. 116 117 // A control destination encapsulates a pair of jump targets and a 118 // flag indicating which one is the preferred fall-through. The 119 // preferred fall-through must be unbound, the other may be already 120 // bound (ie, a backward target). 121 // 122 // The true and false targets may be jumped to unconditionally or 123 // control may split conditionally. Unconditional jumping and 124 // splitting should be emitted in tail position (as the last thing 125 // when compiling an expression) because they can cause either label 126 // to be bound or the non-fall through to be jumped to leaving an 127 // invalid virtual frame. 128 // 129 // The labels in the control destination can be extracted and 130 // manipulated normally without affecting the state of the 131 // destination. 132 133 class ControlDestination BASE_EMBEDDED { 134 public: 135 ControlDestination(JumpTarget* true_target, 136 JumpTarget* false_target, 137 bool true_is_fall_through) 138 : true_target_(true_target), 139 false_target_(false_target), 140 true_is_fall_through_(true_is_fall_through), 141 is_used_(false) { 142 ASSERT(true_is_fall_through ? !true_target->is_bound() 143 : !false_target->is_bound()); 144 } 145 146 // Accessors for the jump targets. Directly jumping or branching to 147 // or binding the targets will not update the destination's state. 148 JumpTarget* true_target() const { return true_target_; } 149 JumpTarget* false_target() const { return false_target_; } 150 151 // True if the the destination has been jumped to unconditionally or 152 // control has been split to both targets. This predicate does not 153 // test whether the targets have been extracted and manipulated as 154 // raw jump targets. 155 bool is_used() const { return is_used_; } 156 157 // True if the destination is used and the true target (respectively 158 // false target) was the fall through. If the target is backward, 159 // "fall through" included jumping unconditionally to it. 160 bool true_was_fall_through() const { 161 return is_used_ && true_is_fall_through_; 162 } 163 164 bool false_was_fall_through() const { 165 return is_used_ && !true_is_fall_through_; 166 } 167 168 // Emit a branch to one of the true or false targets, and bind the 169 // other target. Because this binds the fall-through target, it 170 // should be emitted in tail position (as the last thing when 171 // compiling an expression). 172 void Split(Condition cc) { 173 ASSERT(!is_used_); 174 if (true_is_fall_through_) { 175 false_target_->Branch(NegateCondition(cc)); 176 true_target_->Bind(); 177 } else { 178 true_target_->Branch(cc); 179 false_target_->Bind(); 180 } 181 is_used_ = true; 182 } 183 184 // Emit an unconditional jump in tail position, to the true target 185 // (if the argument is true) or the false target. The "jump" will 186 // actually bind the jump target if it is forward, jump to it if it 187 // is backward. 188 void Goto(bool where) { 189 ASSERT(!is_used_); 190 JumpTarget* target = where ? true_target_ : false_target_; 191 if (target->is_bound()) { 192 target->Jump(); 193 } else { 194 target->Bind(); 195 } 196 is_used_ = true; 197 true_is_fall_through_ = where; 198 } 199 200 // Mark this jump target as used as if Goto had been called, but 201 // without generating a jump or binding a label (the control effect 202 // should have already happened). This is used when the left 203 // subexpression of the short-circuit boolean operators are 204 // compiled. 205 void Use(bool where) { 206 ASSERT(!is_used_); 207 ASSERT((where ? true_target_ : false_target_)->is_bound()); 208 is_used_ = true; 209 true_is_fall_through_ = where; 210 } 211 212 // Swap the true and false targets but keep the same actual label as 213 // the fall through. This is used when compiling negated 214 // expressions, where we want to swap the targets but preserve the 215 // state. 216 void Invert() { 217 JumpTarget* temp_target = true_target_; 218 true_target_ = false_target_; 219 false_target_ = temp_target; 220 221 true_is_fall_through_ = !true_is_fall_through_; 222 } 223 224 private: 225 // True and false jump targets. 226 JumpTarget* true_target_; 227 JumpTarget* false_target_; 228 229 // Before using the destination: true if the true target is the 230 // preferred fall through, false if the false target is. After 231 // using the destination: true if the true target was actually used 232 // as the fall through, false if the false target was. 233 bool true_is_fall_through_; 234 235 // True if the Split or Goto functions have been called. 236 bool is_used_; 237 }; 238 239 240 // ------------------------------------------------------------------------- 241 // Code generation state 242 243 // The state is passed down the AST by the code generator (and back up, in 244 // the form of the state of the jump target pair). It is threaded through 245 // the call stack. Constructing a state implicitly pushes it on the owning 246 // code generator's stack of states, and destroying one implicitly pops it. 247 // 248 // The code generator state is only used for expressions, so statements have 249 // the initial state. 250 251 class CodeGenState BASE_EMBEDDED { 252 public: 253 // Create an initial code generator state. Destroying the initial state 254 // leaves the code generator with a NULL state. 255 explicit CodeGenState(CodeGenerator* owner); 256 257 // Create a code generator state based on a code generator's current 258 // state. The new state has its own control destination. 259 CodeGenState(CodeGenerator* owner, ControlDestination* destination); 260 261 // Destroy a code generator state and restore the owning code generator's 262 // previous state. 263 ~CodeGenState(); 264 265 // Accessors for the state. 266 ControlDestination* destination() const { return destination_; } 267 268 private: 269 // The owning code generator. 270 CodeGenerator* owner_; 271 272 // A control destination in case the expression has a control-flow 273 // effect. 274 ControlDestination* destination_; 275 276 // The previous state of the owning code generator, restored when 277 // this state is destroyed. 278 CodeGenState* previous_; 279 }; 280 281 282 // ------------------------------------------------------------------------- 283 // Arguments allocation mode. 284 285 enum ArgumentsAllocationMode { 286 NO_ARGUMENTS_ALLOCATION, 287 EAGER_ARGUMENTS_ALLOCATION, 288 LAZY_ARGUMENTS_ALLOCATION 289 }; 290 291 292 // ------------------------------------------------------------------------- 293 // CodeGenerator 294 295 class CodeGenerator: public AstVisitor { 296 public: 297 // Takes a function literal, generates code for it. This function should only 298 // be called by compiler.cc. 299 static Handle<Code> MakeCode(CompilationInfo* info); 300 301 // Printing of AST, etc. as requested by flags. 302 static void MakeCodePrologue(CompilationInfo* info); 303 304 // Allocate and install the code. 305 static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm, 306 Code::Flags flags, 307 CompilationInfo* info); 308 309 #ifdef ENABLE_LOGGING_AND_PROFILING 310 static bool ShouldGenerateLog(Expression* type); 311 #endif 312 313 static void RecordPositions(MacroAssembler* masm, int pos); 314 315 // Accessors 316 MacroAssembler* masm() { return masm_; } 317 VirtualFrame* frame() const { return frame_; } 318 inline Handle<Script> script(); 319 320 bool has_valid_frame() const { return frame_ != NULL; } 321 322 // Set the virtual frame to be new_frame, with non-frame register 323 // reference counts given by non_frame_registers. The non-frame 324 // register reference counts of the old frame are returned in 325 // non_frame_registers. 326 void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers); 327 328 void DeleteFrame(); 329 330 RegisterAllocator* allocator() const { return allocator_; } 331 332 CodeGenState* state() { return state_; } 333 void set_state(CodeGenState* state) { state_ = state; } 334 335 void AddDeferred(DeferredCode* code) { deferred_.Add(code); } 336 337 bool in_spilled_code() const { return in_spilled_code_; } 338 void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; } 339 340 private: 341 // Construction/Destruction 342 explicit CodeGenerator(MacroAssembler* masm); 343 344 // Accessors 345 inline bool is_eval(); 346 Scope* scope(); 347 348 // Generating deferred code. 349 void ProcessDeferred(); 350 351 // State 352 ControlDestination* destination() const { return state_->destination(); } 353 354 // Track loop nesting level. 355 int loop_nesting() const { return loop_nesting_; } 356 void IncrementLoopNesting() { loop_nesting_++; } 357 void DecrementLoopNesting() { loop_nesting_--; } 358 359 // Node visitors. 360 void VisitStatements(ZoneList<Statement*>* statements); 361 362 #define DEF_VISIT(type) \ 363 void Visit##type(type* node); 364 AST_NODE_LIST(DEF_VISIT) 365 #undef DEF_VISIT 366 367 // Visit a statement and then spill the virtual frame if control flow can 368 // reach the end of the statement (ie, it does not exit via break, 369 // continue, return, or throw). This function is used temporarily while 370 // the code generator is being transformed. 371 void VisitAndSpill(Statement* statement); 372 373 // Visit a list of statements and then spill the virtual frame if control 374 // flow can reach the end of the list. 375 void VisitStatementsAndSpill(ZoneList<Statement*>* statements); 376 377 // Main code generation function 378 void Generate(CompilationInfo* info); 379 380 // Generate the return sequence code. Should be called no more than 381 // once per compiled function, immediately after binding the return 382 // target (which can not be done more than once). 383 void GenerateReturnSequence(Result* return_value); 384 385 // Returns the arguments allocation mode. 386 ArgumentsAllocationMode ArgumentsMode(); 387 388 // Store the arguments object and allocate it if necessary. 389 Result StoreArgumentsObject(bool initial); 390 391 // The following are used by class Reference. 392 void LoadReference(Reference* ref); 393 void UnloadReference(Reference* ref); 394 395 static Operand ContextOperand(Register context, int index) { 396 return Operand(context, Context::SlotOffset(index)); 397 } 398 399 Operand SlotOperand(Slot* slot, Register tmp); 400 401 Operand ContextSlotOperandCheckExtensions(Slot* slot, 402 Result tmp, 403 JumpTarget* slow); 404 405 // Expressions 406 static Operand GlobalObject() { 407 return ContextOperand(esi, Context::GLOBAL_INDEX); 408 } 409 410 void LoadCondition(Expression* x, 411 ControlDestination* destination, 412 bool force_control); 413 void Load(Expression* expr); 414 void LoadGlobal(); 415 void LoadGlobalReceiver(); 416 417 // Generate code to push the value of an expression on top of the frame 418 // and then spill the frame fully to memory. This function is used 419 // temporarily while the code generator is being transformed. 420 void LoadAndSpill(Expression* expression); 421 422 // Read a value from a slot and leave it on top of the expression stack. 423 Result LoadFromSlot(Slot* slot, TypeofState typeof_state); 424 Result LoadFromSlotCheckForArguments(Slot* slot, TypeofState typeof_state); 425 Result LoadFromGlobalSlotCheckExtensions(Slot* slot, 426 TypeofState typeof_state, 427 JumpTarget* slow); 428 429 // Store the value on top of the expression stack into a slot, leaving the 430 // value in place. 431 void StoreToSlot(Slot* slot, InitState init_state); 432 433 // Support for compiling assignment expressions. 434 void EmitSlotAssignment(Assignment* node); 435 void EmitNamedPropertyAssignment(Assignment* node); 436 void EmitKeyedPropertyAssignment(Assignment* node); 437 438 // Receiver is passed on the frame and consumed. 439 Result EmitNamedLoad(Handle<String> name, bool is_contextual); 440 441 // If the store is contextual, value is passed on the frame and consumed. 442 // Otherwise, receiver and value are passed on the frame and consumed. 443 Result EmitNamedStore(Handle<String> name, bool is_contextual); 444 445 // Receiver and key are passed on the frame and consumed. 446 Result EmitKeyedLoad(); 447 448 // Receiver, key, and value are passed on the frame and consumed. 449 Result EmitKeyedStore(StaticType* key_type); 450 451 // Special code for typeof expressions: Unfortunately, we must 452 // be careful when loading the expression in 'typeof' 453 // expressions. We are not allowed to throw reference errors for 454 // non-existing properties of the global object, so we must make it 455 // look like an explicit property access, instead of an access 456 // through the context chain. 457 void LoadTypeofExpression(Expression* x); 458 459 // Translate the value on top of the frame into control flow to the 460 // control destination. 461 void ToBoolean(ControlDestination* destination); 462 463 void GenericBinaryOperation( 464 Token::Value op, 465 StaticType* type, 466 OverwriteMode overwrite_mode); 467 468 // If possible, combine two constant smi values using op to produce 469 // a smi result, and push it on the virtual frame, all at compile time. 470 // Returns true if it succeeds. Otherwise it has no effect. 471 bool FoldConstantSmis(Token::Value op, int left, int right); 472 473 // Emit code to perform a binary operation on a constant 474 // smi and a likely smi. Consumes the Result *operand. 475 Result ConstantSmiBinaryOperation(Token::Value op, 476 Result* operand, 477 Handle<Object> constant_operand, 478 StaticType* type, 479 bool reversed, 480 OverwriteMode overwrite_mode); 481 482 // Emit code to perform a binary operation on two likely smis. 483 // The code to handle smi arguments is produced inline. 484 // Consumes the Results *left and *right. 485 Result LikelySmiBinaryOperation(Token::Value op, 486 Result* left, 487 Result* right, 488 OverwriteMode overwrite_mode); 489 490 void Comparison(AstNode* node, 491 Condition cc, 492 bool strict, 493 ControlDestination* destination); 494 495 // To prevent long attacker-controlled byte sequences, integer constants 496 // from the JavaScript source are loaded in two parts if they are larger 497 // than 16 bits. 498 static const int kMaxSmiInlinedBits = 16; 499 bool IsUnsafeSmi(Handle<Object> value); 500 // Load an integer constant x into a register target or into the stack using 501 // at most 16 bits of user-controlled data per assembly operation. 502 void MoveUnsafeSmi(Register target, Handle<Object> value); 503 void StoreUnsafeSmiToLocal(int offset, Handle<Object> value); 504 void PushUnsafeSmi(Handle<Object> value); 505 506 void CallWithArguments(ZoneList<Expression*>* arguments, 507 CallFunctionFlags flags, 508 int position); 509 510 // An optimized implementation of expressions of the form 511 // x.apply(y, arguments). We call x the applicand and y the receiver. 512 // The optimization avoids allocating an arguments object if possible. 513 void CallApplyLazy(Expression* applicand, 514 Expression* receiver, 515 VariableProxy* arguments, 516 int position); 517 518 void CheckStack(); 519 520 struct InlineRuntimeLUT { 521 void (CodeGenerator::*method)(ZoneList<Expression*>*); 522 const char* name; 523 }; 524 525 static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name); 526 bool CheckForInlineRuntimeCall(CallRuntime* node); 527 static bool PatchInlineRuntimeEntry(Handle<String> name, 528 const InlineRuntimeLUT& new_entry, 529 InlineRuntimeLUT* old_entry); 530 531 void ProcessDeclarations(ZoneList<Declaration*>* declarations); 532 533 static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop); 534 535 // Declare global variables and functions in the given array of 536 // name/value pairs. 537 void DeclareGlobals(Handle<FixedArray> pairs); 538 539 // Instantiate the function boilerplate. 540 Result InstantiateBoilerplate(Handle<JSFunction> boilerplate); 541 542 // Support for type checks. 543 void GenerateIsSmi(ZoneList<Expression*>* args); 544 void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args); 545 void GenerateIsArray(ZoneList<Expression*>* args); 546 void GenerateIsRegExp(ZoneList<Expression*>* args); 547 void GenerateIsObject(ZoneList<Expression*>* args); 548 void GenerateIsFunction(ZoneList<Expression*>* args); 549 void GenerateIsUndetectableObject(ZoneList<Expression*>* args); 550 551 // Support for construct call checks. 552 void GenerateIsConstructCall(ZoneList<Expression*>* args); 553 554 // Support for arguments.length and arguments[?]. 555 void GenerateArgumentsLength(ZoneList<Expression*>* args); 556 void GenerateArgumentsAccess(ZoneList<Expression*>* args); 557 558 // Support for accessing the class and value fields of an object. 559 void GenerateClassOf(ZoneList<Expression*>* args); 560 void GenerateValueOf(ZoneList<Expression*>* args); 561 void GenerateSetValueOf(ZoneList<Expression*>* args); 562 563 // Fast support for charCodeAt(n). 564 void GenerateFastCharCodeAt(ZoneList<Expression*>* args); 565 566 // Fast support for object equality testing. 567 void GenerateObjectEquals(ZoneList<Expression*>* args); 568 569 void GenerateLog(ZoneList<Expression*>* args); 570 571 void GenerateGetFramePointer(ZoneList<Expression*>* args); 572 573 // Fast support for Math.random(). 574 void GenerateRandomPositiveSmi(ZoneList<Expression*>* args); 575 576 // Fast support for StringAdd. 577 void GenerateStringAdd(ZoneList<Expression*>* args); 578 579 // Fast support for SubString. 580 void GenerateSubString(ZoneList<Expression*>* args); 581 582 // Fast support for StringCompare. 583 void GenerateStringCompare(ZoneList<Expression*>* args); 584 585 // Support for direct calls from JavaScript to native RegExp code. 586 void GenerateRegExpExec(ZoneList<Expression*>* args); 587 588 // Fast support for number to string. 589 void GenerateNumberToString(ZoneList<Expression*>* args); 590 591 // Fast call to transcendental functions. 592 void GenerateMathSin(ZoneList<Expression*>* args); 593 void GenerateMathCos(ZoneList<Expression*>* args); 594 595 // Simple condition analysis. 596 enum ConditionAnalysis { 597 ALWAYS_TRUE, 598 ALWAYS_FALSE, 599 DONT_KNOW 600 }; 601 ConditionAnalysis AnalyzeCondition(Expression* cond); 602 603 // Methods used to indicate which source code is generated for. Source 604 // positions are collected by the assembler and emitted with the relocation 605 // information. 606 void CodeForFunctionPosition(FunctionLiteral* fun); 607 void CodeForReturnPosition(FunctionLiteral* fun); 608 void CodeForStatementPosition(Statement* stmt); 609 void CodeForDoWhileConditionPosition(DoWhileStatement* stmt); 610 void CodeForSourcePosition(int pos); 611 612 #ifdef DEBUG 613 // True if the registers are valid for entry to a block. There should 614 // be no frame-external references to (non-reserved) registers. 615 bool HasValidEntryRegisters(); 616 #endif 617 618 ZoneList<DeferredCode*> deferred_; 619 620 // Assembler 621 MacroAssembler* masm_; // to generate code 622 623 CompilationInfo* info_; 624 625 // Code generation state 626 VirtualFrame* frame_; 627 RegisterAllocator* allocator_; 628 CodeGenState* state_; 629 int loop_nesting_; 630 631 // Jump targets. 632 // The target of the return from the function. 633 BreakTarget function_return_; 634 635 // True if the function return is shadowed (ie, jumping to the target 636 // function_return_ does not jump to the true function return, but rather 637 // to some unlinking code). 638 bool function_return_is_shadowed_; 639 640 // True when we are in code that expects the virtual frame to be fully 641 // spilled. Some virtual frame function are disabled in DEBUG builds when 642 // called from spilled code, because they do not leave the virtual frame 643 // in a spilled state. 644 bool in_spilled_code_; 645 646 static InlineRuntimeLUT kInlineRuntimeLUT[]; 647 648 friend class VirtualFrame; 649 friend class JumpTarget; 650 friend class Reference; 651 friend class Result; 652 friend class FastCodeGenerator; 653 friend class FullCodeGenerator; 654 friend class FullCodeGenSyntaxChecker; 655 656 friend class CodeGeneratorPatcher; // Used in test-log-stack-tracer.cc 657 658 DISALLOW_COPY_AND_ASSIGN(CodeGenerator); 659 }; 660 661 662 // Compute a transcendental math function natively, or call the 663 // TranscendentalCache runtime function. 664 class TranscendentalCacheStub: public CodeStub { 665 public: 666 explicit TranscendentalCacheStub(TranscendentalCache::Type type) 667 : type_(type) {} 668 void Generate(MacroAssembler* masm); 669 private: 670 TranscendentalCache::Type type_; 671 Major MajorKey() { return TranscendentalCache; } 672 int MinorKey() { return type_; } 673 Runtime::FunctionId RuntimeFunction(); 674 void GenerateOperation(MacroAssembler* masm); 675 }; 676 677 678 // Flag that indicates how to generate code for the stub GenericBinaryOpStub. 679 enum GenericBinaryFlags { 680 NO_GENERIC_BINARY_FLAGS = 0, 681 NO_SMI_CODE_IN_STUB = 1 << 0 // Omit smi code in stub. 682 }; 683 684 685 class GenericBinaryOpStub: public CodeStub { 686 public: 687 GenericBinaryOpStub(Token::Value op, 688 OverwriteMode mode, 689 GenericBinaryFlags flags, 690 NumberInfo::Type operands_type = NumberInfo::kUnknown) 691 : op_(op), 692 mode_(mode), 693 flags_(flags), 694 args_in_registers_(false), 695 args_reversed_(false), 696 name_(NULL), 697 operands_type_(operands_type) { 698 use_sse3_ = CpuFeatures::IsSupported(SSE3); 699 ASSERT(OpBits::is_valid(Token::NUM_TOKENS)); 700 } 701 702 // Generate code to call the stub with the supplied arguments. This will add 703 // code at the call site to prepare arguments either in registers or on the 704 // stack together with the actual call. 705 void GenerateCall(MacroAssembler* masm, Register left, Register right); 706 void GenerateCall(MacroAssembler* masm, Register left, Smi* right); 707 void GenerateCall(MacroAssembler* masm, Smi* left, Register right); 708 709 Result GenerateCall(MacroAssembler* masm, 710 VirtualFrame* frame, 711 Result* left, 712 Result* right); 713 714 private: 715 Token::Value op_; 716 OverwriteMode mode_; 717 GenericBinaryFlags flags_; 718 bool args_in_registers_; // Arguments passed in registers not on the stack. 719 bool args_reversed_; // Left and right argument are swapped. 720 bool use_sse3_; 721 char* name_; 722 NumberInfo::Type operands_type_; // Number type information of operands. 723 724 const char* GetName(); 725 726 #ifdef DEBUG 727 void Print() { 728 PrintF("GenericBinaryOpStub %d (op %s), " 729 "(mode %d, flags %d, registers %d, reversed %d, number_info %s)\n", 730 MinorKey(), 731 Token::String(op_), 732 static_cast<int>(mode_), 733 static_cast<int>(flags_), 734 static_cast<int>(args_in_registers_), 735 static_cast<int>(args_reversed_), 736 NumberInfo::ToString(operands_type_)); 737 } 738 #endif 739 740 // Minor key encoding in 16 bits NNNFRASOOOOOOOMM. 741 class ModeBits: public BitField<OverwriteMode, 0, 2> {}; 742 class OpBits: public BitField<Token::Value, 2, 7> {}; 743 class SSE3Bits: public BitField<bool, 9, 1> {}; 744 class ArgsInRegistersBits: public BitField<bool, 10, 1> {}; 745 class ArgsReversedBits: public BitField<bool, 11, 1> {}; 746 class FlagBits: public BitField<GenericBinaryFlags, 12, 1> {}; 747 class NumberInfoBits: public BitField<NumberInfo::Type, 13, 3> {}; 748 749 Major MajorKey() { return GenericBinaryOp; } 750 int MinorKey() { 751 // Encode the parameters in a unique 16 bit value. 752 return OpBits::encode(op_) 753 | ModeBits::encode(mode_) 754 | FlagBits::encode(flags_) 755 | SSE3Bits::encode(use_sse3_) 756 | ArgsInRegistersBits::encode(args_in_registers_) 757 | ArgsReversedBits::encode(args_reversed_) 758 | NumberInfoBits::encode(operands_type_); 759 } 760 761 void Generate(MacroAssembler* masm); 762 void GenerateSmiCode(MacroAssembler* masm, Label* slow); 763 void GenerateLoadArguments(MacroAssembler* masm); 764 void GenerateReturn(MacroAssembler* masm); 765 void GenerateHeapResultAllocation(MacroAssembler* masm, Label* alloc_failure); 766 767 bool ArgsInRegistersSupported() { 768 return op_ == Token::ADD || op_ == Token::SUB 769 || op_ == Token::MUL || op_ == Token::DIV; 770 } 771 bool IsOperationCommutative() { 772 return (op_ == Token::ADD) || (op_ == Token::MUL); 773 } 774 775 void SetArgsInRegisters() { args_in_registers_ = true; } 776 void SetArgsReversed() { args_reversed_ = true; } 777 bool HasSmiCodeInStub() { return (flags_ & NO_SMI_CODE_IN_STUB) == 0; } 778 bool HasArgsInRegisters() { return args_in_registers_; } 779 bool HasArgsReversed() { return args_reversed_; } 780 }; 781 782 783 class StringStubBase: public CodeStub { 784 public: 785 // Generate code for copying characters using a simple loop. This should only 786 // be used in places where the number of characters is small and the 787 // additional setup and checking in GenerateCopyCharactersREP adds too much 788 // overhead. Copying of overlapping regions is not supported. 789 void GenerateCopyCharacters(MacroAssembler* masm, 790 Register dest, 791 Register src, 792 Register count, 793 Register scratch, 794 bool ascii); 795 796 // Generate code for copying characters using the rep movs instruction. 797 // Copies ecx characters from esi to edi. Copying of overlapping regions is 798 // not supported. 799 void GenerateCopyCharactersREP(MacroAssembler* masm, 800 Register dest, // Must be edi. 801 Register src, // Must be esi. 802 Register count, // Must be ecx. 803 Register scratch, // Neither of the above. 804 bool ascii); 805 806 // Probe the symbol table for a two character string. If the string is 807 // not found by probing a jump to the label not_found is performed. This jump 808 // does not guarantee that the string is not in the symbol table. If the 809 // string is found the code falls through with the string in register eax. 810 void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, 811 Register c1, 812 Register c2, 813 Register scratch1, 814 Register scratch2, 815 Register scratch3, 816 Label* not_found); 817 818 // Generate string hash. 819 void GenerateHashInit(MacroAssembler* masm, 820 Register hash, 821 Register character, 822 Register scratch); 823 void GenerateHashAddCharacter(MacroAssembler* masm, 824 Register hash, 825 Register character, 826 Register scratch); 827 void GenerateHashGetHash(MacroAssembler* masm, 828 Register hash, 829 Register scratch); 830 }; 831 832 833 // Flag that indicates how to generate code for the stub StringAddStub. 834 enum StringAddFlags { 835 NO_STRING_ADD_FLAGS = 0, 836 NO_STRING_CHECK_IN_STUB = 1 << 0 // Omit string check in stub. 837 }; 838 839 840 class StringAddStub: public StringStubBase { 841 public: 842 explicit StringAddStub(StringAddFlags flags) { 843 string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0); 844 } 845 846 private: 847 Major MajorKey() { return StringAdd; } 848 int MinorKey() { return string_check_ ? 0 : 1; } 849 850 void Generate(MacroAssembler* masm); 851 852 // Should the stub check whether arguments are strings? 853 bool string_check_; 854 }; 855 856 857 class SubStringStub: public StringStubBase { 858 public: 859 SubStringStub() {} 860 861 private: 862 Major MajorKey() { return SubString; } 863 int MinorKey() { return 0; } 864 865 void Generate(MacroAssembler* masm); 866 }; 867 868 869 class StringCompareStub: public StringStubBase { 870 public: 871 explicit StringCompareStub() { 872 } 873 874 // Compare two flat ascii strings and returns result in eax after popping two 875 // arguments from the stack. 876 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 877 Register left, 878 Register right, 879 Register scratch1, 880 Register scratch2, 881 Register scratch3); 882 883 private: 884 Major MajorKey() { return StringCompare; } 885 int MinorKey() { return 0; } 886 887 void Generate(MacroAssembler* masm); 888 }; 889 890 891 class NumberToStringStub: public CodeStub { 892 public: 893 NumberToStringStub() { } 894 895 // Generate code to do a lookup in the number string cache. If the number in 896 // the register object is found in the cache the generated code falls through 897 // with the result in the result register. The object and the result register 898 // can be the same. If the number is not found in the cache the code jumps to 899 // the label not_found with only the content of register object unchanged. 900 static void GenerateLookupNumberStringCache(MacroAssembler* masm, 901 Register object, 902 Register result, 903 Register scratch1, 904 Register scratch2, 905 bool object_is_smi, 906 Label* not_found); 907 908 private: 909 Major MajorKey() { return NumberToString; } 910 int MinorKey() { return 0; } 911 912 void Generate(MacroAssembler* masm); 913 914 const char* GetName() { return "NumberToStringStub"; } 915 916 #ifdef DEBUG 917 void Print() { 918 PrintF("NumberToStringStub\n"); 919 } 920 #endif 921 }; 922 923 924 } } // namespace v8::internal 925 926 #endif // V8_IA32_CODEGEN_IA32_H_ 927