| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 RegisterAllocator* allocator() const { return allocator_; } | 332 RegisterAllocator* allocator() const { return allocator_; } |
| 333 | 333 |
| 334 CodeGenState* state() { return state_; } | 334 CodeGenState* state() { return state_; } |
| 335 void set_state(CodeGenState* state) { state_ = state; } | 335 void set_state(CodeGenState* state) { state_ = state; } |
| 336 | 336 |
| 337 void AddDeferred(DeferredCode* code) { deferred_.Add(code); } | 337 void AddDeferred(DeferredCode* code) { deferred_.Add(code); } |
| 338 | 338 |
| 339 bool in_spilled_code() const { return in_spilled_code_; } | 339 bool in_spilled_code() const { return in_spilled_code_; } |
| 340 void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; } | 340 void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; } |
| 341 | 341 |
| 342 // If the name is an inline runtime function call return the number of |
| 343 // expected arguments. Otherwise return -1. |
| 344 static int InlineRuntimeCallArgumentsCount(Handle<String> name); |
| 345 |
| 342 private: | 346 private: |
| 343 // Construction/Destruction | 347 // Construction/Destruction |
| 344 explicit CodeGenerator(MacroAssembler* masm); | 348 explicit CodeGenerator(MacroAssembler* masm); |
| 345 | 349 |
| 346 // Accessors | 350 // Accessors |
| 347 inline bool is_eval(); | 351 inline bool is_eval(); |
| 348 inline Scope* scope(); | 352 inline Scope* scope(); |
| 349 | 353 |
| 350 // Generating deferred code. | 354 // Generating deferred code. |
| 351 void ProcessDeferred(); | 355 void ProcessDeferred(); |
| 352 | 356 |
| 353 // State | 357 // State |
| 354 ControlDestination* destination() const { return state_->destination(); } | 358 ControlDestination* destination() const { return state_->destination(); } |
| 355 | 359 |
| 360 // Control of side-effect-free int32 expression compilation. |
| 361 bool in_safe_int32_mode() { return in_safe_int32_mode_; } |
| 362 void set_in_safe_int32_mode(bool value) { in_safe_int32_mode_ = value; } |
| 363 bool safe_int32_mode_enabled() { |
| 364 return FLAG_safe_int32_compiler && safe_int32_mode_enabled_; |
| 365 } |
| 366 void set_safe_int32_mode_enabled(bool value) { |
| 367 safe_int32_mode_enabled_ = value; |
| 368 } |
| 369 void set_unsafe_bailout(BreakTarget* unsafe_bailout) { |
| 370 unsafe_bailout_ = unsafe_bailout; |
| 371 } |
| 372 |
| 373 // Take the Result that is an untagged int32, and convert it to a tagged |
| 374 // Smi or HeapNumber. Remove the untagged_int32 flag from the result. |
| 375 void ConvertInt32ResultToNumber(Result* value); |
| 376 |
| 356 // Track loop nesting level. | 377 // Track loop nesting level. |
| 357 int loop_nesting() const { return loop_nesting_; } | 378 int loop_nesting() const { return loop_nesting_; } |
| 358 void IncrementLoopNesting() { loop_nesting_++; } | 379 void IncrementLoopNesting() { loop_nesting_++; } |
| 359 void DecrementLoopNesting() { loop_nesting_--; } | 380 void DecrementLoopNesting() { loop_nesting_--; } |
| 360 | 381 |
| 361 // Node visitors. | 382 // Node visitors. |
| 362 void VisitStatements(ZoneList<Statement*>* statements); | 383 void VisitStatements(ZoneList<Statement*>* statements); |
| 363 | 384 |
| 364 #define DEF_VISIT(type) \ | 385 #define DEF_VISIT(type) \ |
| 365 void Visit##type(type* node); | 386 void Visit##type(type* node); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 | 423 |
| 403 Operand ContextSlotOperandCheckExtensions(Slot* slot, | 424 Operand ContextSlotOperandCheckExtensions(Slot* slot, |
| 404 Result tmp, | 425 Result tmp, |
| 405 JumpTarget* slow); | 426 JumpTarget* slow); |
| 406 | 427 |
| 407 // Expressions | 428 // Expressions |
| 408 static Operand GlobalObject() { | 429 static Operand GlobalObject() { |
| 409 return ContextOperand(esi, Context::GLOBAL_INDEX); | 430 return ContextOperand(esi, Context::GLOBAL_INDEX); |
| 410 } | 431 } |
| 411 | 432 |
| 412 void LoadCondition(Expression* x, | 433 void LoadCondition(Expression* expr, |
| 413 ControlDestination* destination, | 434 ControlDestination* destination, |
| 414 bool force_control); | 435 bool force_control); |
| 415 void Load(Expression* expr); | 436 void Load(Expression* expr); |
| 416 void LoadGlobal(); | 437 void LoadGlobal(); |
| 417 void LoadGlobalReceiver(); | 438 void LoadGlobalReceiver(); |
| 418 | 439 |
| 419 // Generate code to push the value of an expression on top of the frame | 440 // Generate code to push the value of an expression on top of the frame |
| 420 // and then spill the frame fully to memory. This function is used | 441 // and then spill the frame fully to memory. This function is used |
| 421 // temporarily while the code generator is being transformed. | 442 // temporarily while the code generator is being transformed. |
| 422 void LoadAndSpill(Expression* expression); | 443 void LoadAndSpill(Expression* expression); |
| 423 | 444 |
| 445 // Evaluate an expression and place its value on top of the frame, |
| 446 // using, or not using, the side-effect-free expression compiler. |
| 447 void LoadInSafeInt32Mode(Expression* expr, BreakTarget* unsafe_bailout); |
| 448 void LoadWithSafeInt32ModeDisabled(Expression* expr); |
| 449 |
| 424 // Read a value from a slot and leave it on top of the expression stack. | 450 // Read a value from a slot and leave it on top of the expression stack. |
| 425 Result LoadFromSlot(Slot* slot, TypeofState typeof_state); | 451 Result LoadFromSlot(Slot* slot, TypeofState typeof_state); |
| 426 Result LoadFromSlotCheckForArguments(Slot* slot, TypeofState typeof_state); | 452 Result LoadFromSlotCheckForArguments(Slot* slot, TypeofState typeof_state); |
| 427 Result LoadFromGlobalSlotCheckExtensions(Slot* slot, | 453 Result LoadFromGlobalSlotCheckExtensions(Slot* slot, |
| 428 TypeofState typeof_state, | 454 TypeofState typeof_state, |
| 429 JumpTarget* slow); | 455 JumpTarget* slow); |
| 430 | 456 |
| 431 // Store the value on top of the expression stack into a slot, leaving the | 457 // Store the value on top of the expression stack into a slot, leaving the |
| 432 // value in place. | 458 // value in place. |
| 433 void StoreToSlot(Slot* slot, InitState init_state); | 459 void StoreToSlot(Slot* slot, InitState init_state); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 458 // through the context chain. | 484 // through the context chain. |
| 459 void LoadTypeofExpression(Expression* x); | 485 void LoadTypeofExpression(Expression* x); |
| 460 | 486 |
| 461 // Translate the value on top of the frame into control flow to the | 487 // Translate the value on top of the frame into control flow to the |
| 462 // control destination. | 488 // control destination. |
| 463 void ToBoolean(ControlDestination* destination); | 489 void ToBoolean(ControlDestination* destination); |
| 464 | 490 |
| 465 void GenericBinaryOperation( | 491 void GenericBinaryOperation( |
| 466 Token::Value op, | 492 Token::Value op, |
| 467 StaticType* type, | 493 StaticType* type, |
| 468 OverwriteMode overwrite_mode); | 494 OverwriteMode overwrite_mode, |
| 495 bool no_negative_zero); |
| 469 | 496 |
| 470 // If possible, combine two constant smi values using op to produce | 497 // If possible, combine two constant smi values using op to produce |
| 471 // a smi result, and push it on the virtual frame, all at compile time. | 498 // a smi result, and push it on the virtual frame, all at compile time. |
| 472 // Returns true if it succeeds. Otherwise it has no effect. | 499 // Returns true if it succeeds. Otherwise it has no effect. |
| 473 bool FoldConstantSmis(Token::Value op, int left, int right); | 500 bool FoldConstantSmis(Token::Value op, int left, int right); |
| 474 | 501 |
| 475 // Emit code to perform a binary operation on a constant | 502 // Emit code to perform a binary operation on a constant |
| 476 // smi and a likely smi. Consumes the Result *operand. | 503 // smi and a likely smi. Consumes the Result operand. |
| 477 Result ConstantSmiBinaryOperation(Token::Value op, | 504 Result ConstantSmiBinaryOperation(Token::Value op, |
| 478 Result* operand, | 505 Result* operand, |
| 479 Handle<Object> constant_operand, | 506 Handle<Object> constant_operand, |
| 480 StaticType* type, | 507 StaticType* type, |
| 481 bool reversed, | 508 bool reversed, |
| 482 OverwriteMode overwrite_mode); | 509 OverwriteMode overwrite_mode, |
| 510 bool no_negative_zero); |
| 483 | 511 |
| 484 // Emit code to perform a binary operation on two likely smis. | 512 // Emit code to perform a binary operation on two likely smis. |
| 485 // The code to handle smi arguments is produced inline. | 513 // The code to handle smi arguments is produced inline. |
| 486 // Consumes the Results *left and *right. | 514 // Consumes the Results left and right. |
| 487 Result LikelySmiBinaryOperation(Token::Value op, | 515 Result LikelySmiBinaryOperation(Token::Value op, |
| 488 Result* left, | 516 Result* left, |
| 489 Result* right, | 517 Result* right, |
| 490 OverwriteMode overwrite_mode); | 518 OverwriteMode overwrite_mode, |
| 519 bool no_negative_zero); |
| 520 |
| 521 |
| 522 // Emit code to perform a binary operation on two untagged int32 values. |
| 523 // The values are on top of the frame, and the result is pushed on the frame. |
| 524 void Int32BinaryOperation(BinaryOperation* node); |
| 525 |
| 491 | 526 |
| 492 void Comparison(AstNode* node, | 527 void Comparison(AstNode* node, |
| 493 Condition cc, | 528 Condition cc, |
| 494 bool strict, | 529 bool strict, |
| 495 ControlDestination* destination); | 530 ControlDestination* destination); |
| 496 | 531 |
| 497 // To prevent long attacker-controlled byte sequences, integer constants | 532 // To prevent long attacker-controlled byte sequences, integer constants |
| 498 // from the JavaScript source are loaded in two parts if they are larger | 533 // from the JavaScript source are loaded in two parts if they are larger |
| 499 // than 17 bits. | 534 // than 17 bits. |
| 500 static const int kMaxSmiInlinedBits = 17; | 535 static const int kMaxSmiInlinedBits = 17; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 515 void CallApplyLazy(Expression* applicand, | 550 void CallApplyLazy(Expression* applicand, |
| 516 Expression* receiver, | 551 Expression* receiver, |
| 517 VariableProxy* arguments, | 552 VariableProxy* arguments, |
| 518 int position); | 553 int position); |
| 519 | 554 |
| 520 void CheckStack(); | 555 void CheckStack(); |
| 521 | 556 |
| 522 struct InlineRuntimeLUT { | 557 struct InlineRuntimeLUT { |
| 523 void (CodeGenerator::*method)(ZoneList<Expression*>*); | 558 void (CodeGenerator::*method)(ZoneList<Expression*>*); |
| 524 const char* name; | 559 const char* name; |
| 560 int nargs; |
| 525 }; | 561 }; |
| 526 | 562 |
| 527 static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name); | 563 static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name); |
| 528 bool CheckForInlineRuntimeCall(CallRuntime* node); | 564 bool CheckForInlineRuntimeCall(CallRuntime* node); |
| 529 static bool PatchInlineRuntimeEntry(Handle<String> name, | 565 static bool PatchInlineRuntimeEntry(Handle<String> name, |
| 530 const InlineRuntimeLUT& new_entry, | 566 const InlineRuntimeLUT& new_entry, |
| 531 InlineRuntimeLUT* old_entry); | 567 InlineRuntimeLUT* old_entry); |
| 532 | 568 |
| 533 void ProcessDeclarations(ZoneList<Declaration*>* declarations); | 569 void ProcessDeclarations(ZoneList<Declaration*>* declarations); |
| 534 | 570 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 548 void GenerateIsRegExp(ZoneList<Expression*>* args); | 584 void GenerateIsRegExp(ZoneList<Expression*>* args); |
| 549 void GenerateIsObject(ZoneList<Expression*>* args); | 585 void GenerateIsObject(ZoneList<Expression*>* args); |
| 550 void GenerateIsFunction(ZoneList<Expression*>* args); | 586 void GenerateIsFunction(ZoneList<Expression*>* args); |
| 551 void GenerateIsUndetectableObject(ZoneList<Expression*>* args); | 587 void GenerateIsUndetectableObject(ZoneList<Expression*>* args); |
| 552 | 588 |
| 553 // Support for construct call checks. | 589 // Support for construct call checks. |
| 554 void GenerateIsConstructCall(ZoneList<Expression*>* args); | 590 void GenerateIsConstructCall(ZoneList<Expression*>* args); |
| 555 | 591 |
| 556 // Support for arguments.length and arguments[?]. | 592 // Support for arguments.length and arguments[?]. |
| 557 void GenerateArgumentsLength(ZoneList<Expression*>* args); | 593 void GenerateArgumentsLength(ZoneList<Expression*>* args); |
| 558 void GenerateArgumentsAccess(ZoneList<Expression*>* args); | 594 void GenerateArguments(ZoneList<Expression*>* args); |
| 559 | 595 |
| 560 // Support for accessing the class and value fields of an object. | 596 // Support for accessing the class and value fields of an object. |
| 561 void GenerateClassOf(ZoneList<Expression*>* args); | 597 void GenerateClassOf(ZoneList<Expression*>* args); |
| 562 void GenerateValueOf(ZoneList<Expression*>* args); | 598 void GenerateValueOf(ZoneList<Expression*>* args); |
| 563 void GenerateSetValueOf(ZoneList<Expression*>* args); | 599 void GenerateSetValueOf(ZoneList<Expression*>* args); |
| 564 | 600 |
| 565 // Fast support for charCodeAt(n). | 601 // Fast support for charCodeAt(n). |
| 566 void GenerateFastCharCodeAt(ZoneList<Expression*>* args); | 602 void GenerateFastCharCodeAt(ZoneList<Expression*>* args); |
| 567 | 603 |
| 568 // Fast support for string.charAt(n) and string[n]. | 604 // Fast support for string.charAt(n) and string[n]. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 586 | 622 |
| 587 // Fast support for StringCompare. | 623 // Fast support for StringCompare. |
| 588 void GenerateStringCompare(ZoneList<Expression*>* args); | 624 void GenerateStringCompare(ZoneList<Expression*>* args); |
| 589 | 625 |
| 590 // Support for direct calls from JavaScript to native RegExp code. | 626 // Support for direct calls from JavaScript to native RegExp code. |
| 591 void GenerateRegExpExec(ZoneList<Expression*>* args); | 627 void GenerateRegExpExec(ZoneList<Expression*>* args); |
| 592 | 628 |
| 593 // Fast support for number to string. | 629 // Fast support for number to string. |
| 594 void GenerateNumberToString(ZoneList<Expression*>* args); | 630 void GenerateNumberToString(ZoneList<Expression*>* args); |
| 595 | 631 |
| 596 // Fast support for Math.pow(). | 632 // Fast call to math functions. |
| 597 void GenerateMathPow(ZoneList<Expression*>* args); | 633 void GenerateMathPow(ZoneList<Expression*>* args); |
| 598 | |
| 599 // Fast call to transcendental functions. | |
| 600 void GenerateMathSin(ZoneList<Expression*>* args); | 634 void GenerateMathSin(ZoneList<Expression*>* args); |
| 601 void GenerateMathCos(ZoneList<Expression*>* args); | 635 void GenerateMathCos(ZoneList<Expression*>* args); |
| 602 | |
| 603 // Fast case for sqrt | |
| 604 void GenerateMathSqrt(ZoneList<Expression*>* args); | 636 void GenerateMathSqrt(ZoneList<Expression*>* args); |
| 605 | 637 |
| 606 // Simple condition analysis. | 638 // Simple condition analysis. |
| 607 enum ConditionAnalysis { | 639 enum ConditionAnalysis { |
| 608 ALWAYS_TRUE, | 640 ALWAYS_TRUE, |
| 609 ALWAYS_FALSE, | 641 ALWAYS_FALSE, |
| 610 DONT_KNOW | 642 DONT_KNOW |
| 611 }; | 643 }; |
| 612 ConditionAnalysis AnalyzeCondition(Expression* cond); | 644 ConditionAnalysis AnalyzeCondition(Expression* cond); |
| 613 | 645 |
| 614 // Methods used to indicate which source code is generated for. Source | 646 // Methods used to indicate which source code is generated for. Source |
| 615 // positions are collected by the assembler and emitted with the relocation | 647 // positions are collected by the assembler and emitted with the relocation |
| 616 // information. | 648 // information. |
| 617 void CodeForFunctionPosition(FunctionLiteral* fun); | 649 void CodeForFunctionPosition(FunctionLiteral* fun); |
| 618 void CodeForReturnPosition(FunctionLiteral* fun); | 650 void CodeForReturnPosition(FunctionLiteral* fun); |
| 619 void CodeForStatementPosition(Statement* stmt); | 651 void CodeForStatementPosition(Statement* stmt); |
| 620 void CodeForDoWhileConditionPosition(DoWhileStatement* stmt); | 652 void CodeForDoWhileConditionPosition(DoWhileStatement* stmt); |
| 621 void CodeForSourcePosition(int pos); | 653 void CodeForSourcePosition(int pos); |
| 622 | 654 |
| 655 void SetTypeForStackSlot(Slot* slot, NumberInfo info); |
| 656 |
| 623 #ifdef DEBUG | 657 #ifdef DEBUG |
| 624 // True if the registers are valid for entry to a block. There should | 658 // True if the registers are valid for entry to a block. There should |
| 625 // be no frame-external references to (non-reserved) registers. | 659 // be no frame-external references to (non-reserved) registers. |
| 626 bool HasValidEntryRegisters(); | 660 bool HasValidEntryRegisters(); |
| 627 #endif | 661 #endif |
| 628 | 662 |
| 629 ZoneList<DeferredCode*> deferred_; | 663 ZoneList<DeferredCode*> deferred_; |
| 630 | 664 |
| 631 // Assembler | 665 // Assembler |
| 632 MacroAssembler* masm_; // to generate code | 666 MacroAssembler* masm_; // to generate code |
| 633 | 667 |
| 634 CompilationInfo* info_; | 668 CompilationInfo* info_; |
| 635 | 669 |
| 636 // Code generation state | 670 // Code generation state |
| 637 VirtualFrame* frame_; | 671 VirtualFrame* frame_; |
| 638 RegisterAllocator* allocator_; | 672 RegisterAllocator* allocator_; |
| 639 CodeGenState* state_; | 673 CodeGenState* state_; |
| 640 int loop_nesting_; | 674 int loop_nesting_; |
| 675 bool in_safe_int32_mode_; |
| 676 bool safe_int32_mode_enabled_; |
| 641 | 677 |
| 642 // Jump targets. | 678 // Jump targets. |
| 643 // The target of the return from the function. | 679 // The target of the return from the function. |
| 644 BreakTarget function_return_; | 680 BreakTarget function_return_; |
| 681 // The target of the bailout from a side-effect-free int32 subexpression. |
| 682 BreakTarget* unsafe_bailout_; |
| 645 | 683 |
| 646 // True if the function return is shadowed (ie, jumping to the target | 684 // True if the function return is shadowed (ie, jumping to the target |
| 647 // function_return_ does not jump to the true function return, but rather | 685 // function_return_ does not jump to the true function return, but rather |
| 648 // to some unlinking code). | 686 // to some unlinking code). |
| 649 bool function_return_is_shadowed_; | 687 bool function_return_is_shadowed_; |
| 650 | 688 |
| 651 // True when we are in code that expects the virtual frame to be fully | 689 // True when we are in code that expects the virtual frame to be fully |
| 652 // spilled. Some virtual frame function are disabled in DEBUG builds when | 690 // spilled. Some virtual frame function are disabled in DEBUG builds when |
| 653 // called from spilled code, because they do not leave the virtual frame | 691 // called from spilled code, because they do not leave the virtual frame |
| 654 // in a spilled state. | 692 // in a spilled state. |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 969 const char* GetName() { return "NumberToStringStub"; } | 1007 const char* GetName() { return "NumberToStringStub"; } |
| 970 | 1008 |
| 971 #ifdef DEBUG | 1009 #ifdef DEBUG |
| 972 void Print() { | 1010 void Print() { |
| 973 PrintF("NumberToStringStub\n"); | 1011 PrintF("NumberToStringStub\n"); |
| 974 } | 1012 } |
| 975 #endif | 1013 #endif |
| 976 }; | 1014 }; |
| 977 | 1015 |
| 978 | 1016 |
| 1017 class RecordWriteStub : public CodeStub { |
| 1018 public: |
| 1019 RecordWriteStub(Register object, Register addr, Register scratch) |
| 1020 : object_(object), addr_(addr), scratch_(scratch) { } |
| 1021 |
| 1022 void Generate(MacroAssembler* masm); |
| 1023 |
| 1024 private: |
| 1025 Register object_; |
| 1026 Register addr_; |
| 1027 Register scratch_; |
| 1028 |
| 1029 #ifdef DEBUG |
| 1030 void Print() { |
| 1031 PrintF("RecordWriteStub (object reg %d), (addr reg %d), (scratch reg %d)\n", |
| 1032 object_.code(), addr_.code(), scratch_.code()); |
| 1033 } |
| 1034 #endif |
| 1035 |
| 1036 // Minor key encoding in 12 bits of three registers (object, address and |
| 1037 // scratch) OOOOAAAASSSS. |
| 1038 class ScratchBits: public BitField<uint32_t, 0, 4> {}; |
| 1039 class AddressBits: public BitField<uint32_t, 4, 4> {}; |
| 1040 class ObjectBits: public BitField<uint32_t, 8, 4> {}; |
| 1041 |
| 1042 Major MajorKey() { return RecordWrite; } |
| 1043 |
| 1044 int MinorKey() { |
| 1045 // Encode the registers. |
| 1046 return ObjectBits::encode(object_.code()) | |
| 1047 AddressBits::encode(addr_.code()) | |
| 1048 ScratchBits::encode(scratch_.code()); |
| 1049 } |
| 1050 }; |
| 1051 |
| 1052 |
| 979 } } // namespace v8::internal | 1053 } } // namespace v8::internal |
| 980 | 1054 |
| 981 #endif // V8_IA32_CODEGEN_IA32_H_ | 1055 #endif // V8_IA32_CODEGEN_IA32_H_ |
| OLD | NEW |