| OLD | NEW | 
|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 12 matching lines...) Expand all  Loading... | 
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 27 | 27 | 
| 28 #include "v8.h" | 28 #include "v8.h" | 
| 29 | 29 | 
| 30 #include "bootstrapper.h" | 30 #include "bootstrapper.h" | 
| 31 #include "codegen-inl.h" | 31 #include "codegen-inl.h" | 
| 32 #include "debug.h" | 32 #include "debug.h" | 
| 33 #include "prettyprinter.h" |  | 
| 34 #include "scopeinfo.h" |  | 
| 35 #include "scopes.h" | 33 #include "scopes.h" | 
| 36 #include "runtime.h" | 34 #include "runtime.h" | 
| 37 | 35 | 
| 38 namespace v8 { namespace internal { | 36 namespace v8 { namespace internal { | 
| 39 | 37 | 
| 40 #define TOS (Operand(esp, 0)) | 38 #define TOS (Operand(esp, 0)) | 
| 41 | 39 | 
| 42 | 40 | 
| 43 class Ia32CodeGenerator; |  | 
| 44 |  | 
| 45 // Mode to overwrite BinaryExpression values. |  | 
| 46 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT }; |  | 
| 47 |  | 
| 48 |  | 
| 49 // ----------------------------------------------------------------------------- |  | 
| 50 // Reference support |  | 
| 51 |  | 
| 52 // A reference is a C++ stack-allocated object that keeps an ECMA |  | 
| 53 // reference on the execution stack while in scope. For variables |  | 
| 54 // the reference is empty, indicating that it isn't necessary to |  | 
| 55 // store state on the stack for keeping track of references to those. |  | 
| 56 // For properties, we keep either one (named) or two (indexed) values |  | 
| 57 // on the execution stack to represent the reference. |  | 
| 58 |  | 
| 59 enum InitState { CONST_INIT, NOT_CONST_INIT }; |  | 
| 60 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; |  | 
| 61 |  | 
| 62 class Reference BASE_EMBEDDED { |  | 
| 63  public: |  | 
| 64   // The values of the types is important, see size(). |  | 
| 65   enum Type { ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 }; |  | 
| 66   Reference(Ia32CodeGenerator* cgen, Expression* expression); |  | 
| 67   ~Reference(); |  | 
| 68 |  | 
| 69   Expression* expression() const { return expression_; } |  | 
| 70   Type type() const { return type_; } |  | 
| 71   void set_type(Type value) { |  | 
| 72     ASSERT(type_ == ILLEGAL); |  | 
| 73     type_ = value; |  | 
| 74   } |  | 
| 75 |  | 
| 76   // The size of the reference or -1 if the reference is illegal. |  | 
| 77   int size() const { return type_; } |  | 
| 78 |  | 
| 79   bool is_illegal() const { return type_ == ILLEGAL; } |  | 
| 80   bool is_slot() const { return type_ == SLOT; } |  | 
| 81   bool is_property() const { return type_ == NAMED || type_ == KEYED; } |  | 
| 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 left in place with its value above it. |  | 
| 89   void GetValue(TypeofState typeof_state); |  | 
| 90 |  | 
| 91   // Generate code to store the value on top of the expression stack in the |  | 
| 92   // reference.  The reference is expected to be immediately below the value |  | 
| 93   // on the expression stack.  The stored value is left in place (with the |  | 
| 94   // reference intact below it) to support chained assignments. |  | 
| 95   void SetValue(InitState init_state); |  | 
| 96 |  | 
| 97  private: |  | 
| 98   Ia32CodeGenerator* cgen_; |  | 
| 99   Expression* expression_; |  | 
| 100   Type type_; |  | 
| 101 }; |  | 
| 102 |  | 
| 103 |  | 
| 104 // ------------------------------------------------------------------------- |  | 
| 105 // Code generation state |  | 
| 106 |  | 
| 107 // The state is passed down the AST by the code generator (and back up, in |  | 
| 108 // the form of the state of the label pair).  It is threaded through the |  | 
| 109 // call stack.  Constructing a state implicitly pushes it on the owning code |  | 
| 110 // generator's stack of states, and destroying one implicitly pops it. |  | 
| 111 |  | 
| 112 class CodeGenState BASE_EMBEDDED { |  | 
| 113  public: |  | 
| 114   // Create an initial code generator state.  Destroying the initial state |  | 
| 115   // leaves the code generator with a NULL state. |  | 
| 116   explicit CodeGenState(Ia32CodeGenerator* owner); |  | 
| 117 |  | 
| 118   // Create a code generator state based on a code generator's current |  | 
| 119   // state.  The new state has its own typeof state and pair of branch |  | 
| 120   // labels. |  | 
| 121   CodeGenState(Ia32CodeGenerator* owner, |  | 
| 122                TypeofState typeof_state, |  | 
| 123                Label* true_target, |  | 
| 124                Label* false_target); |  | 
| 125 |  | 
| 126   // Destroy a code generator state and restore the owning code generator's |  | 
| 127   // previous state. |  | 
| 128   ~CodeGenState(); |  | 
| 129 |  | 
| 130   TypeofState typeof_state() const { return typeof_state_; } |  | 
| 131   Label* true_target() const { return true_target_; } |  | 
| 132   Label* false_target() const { return false_target_; } |  | 
| 133 |  | 
| 134  private: |  | 
| 135   Ia32CodeGenerator* owner_; |  | 
| 136   TypeofState typeof_state_; |  | 
| 137   Label* true_target_; |  | 
| 138   Label* false_target_; |  | 
| 139   CodeGenState* previous_; |  | 
| 140 }; |  | 
| 141 |  | 
| 142 |  | 
| 143 // ----------------------------------------------------------------------------- |  | 
| 144 // Ia32CodeGenerator |  | 
| 145 |  | 
| 146 class Ia32CodeGenerator: public CodeGenerator { |  | 
| 147  public: |  | 
| 148   static Handle<Code> MakeCode(FunctionLiteral* fun, |  | 
| 149                                Handle<Script> script, |  | 
| 150                                bool is_eval); |  | 
| 151 |  | 
| 152   MacroAssembler* masm() { return masm_; } |  | 
| 153 |  | 
| 154   Scope* scope() const { return scope_; } |  | 
| 155 |  | 
| 156   CodeGenState* state() { return state_; } |  | 
| 157   void set_state(CodeGenState* state) { state_ = state; } |  | 
| 158 |  | 
| 159  private: |  | 
| 160   // Assembler |  | 
| 161   MacroAssembler* masm_;  // to generate code |  | 
| 162 |  | 
| 163   // Code generation state |  | 
| 164   Scope* scope_; |  | 
| 165   Condition cc_reg_; |  | 
| 166   CodeGenState* state_; |  | 
| 167   bool is_inside_try_; |  | 
| 168   int break_stack_height_; |  | 
| 169 |  | 
| 170   // Labels |  | 
| 171   Label function_return_; |  | 
| 172 |  | 
| 173   // Construction/destruction |  | 
| 174   Ia32CodeGenerator(int buffer_size, |  | 
| 175                     Handle<Script> script, |  | 
| 176                     bool is_eval); |  | 
| 177   virtual ~Ia32CodeGenerator() { delete masm_; } |  | 
| 178 |  | 
| 179   // Main code generation function |  | 
| 180   void GenCode(FunctionLiteral* fun); |  | 
| 181 |  | 
| 182   // The following are used by class Reference. |  | 
| 183   void LoadReference(Reference* ref); |  | 
| 184   void UnloadReference(Reference* ref); |  | 
| 185 |  | 
| 186   // State |  | 
| 187   bool has_cc() const  { return cc_reg_ >= 0; } |  | 
| 188   TypeofState typeof_state() const { return state_->typeof_state(); } |  | 
| 189   Label* true_target() const  { return state_->true_target(); } |  | 
| 190   Label* false_target() const  { return state_->false_target(); } |  | 
| 191 |  | 
| 192   // Expressions |  | 
| 193   Operand GlobalObject() const { |  | 
| 194     return ContextOperand(esi, Context::GLOBAL_INDEX); |  | 
| 195   } |  | 
| 196 |  | 
| 197   // Support functions for accessing parameters. |  | 
| 198   Operand ParameterOperand(int index) const { |  | 
| 199     int num_parameters = scope()->num_parameters(); |  | 
| 200     ASSERT(-2 <= index && index < num_parameters); |  | 
| 201     return Operand(ebp, (1 + num_parameters - index) * kPointerSize); |  | 
| 202   } |  | 
| 203 |  | 
| 204   Operand ReceiverOperand() const { return ParameterOperand(-1); } |  | 
| 205 |  | 
| 206   Operand FunctionOperand() const { |  | 
| 207     return Operand(ebp, JavaScriptFrameConstants::kFunctionOffset); |  | 
| 208   } |  | 
| 209 |  | 
| 210   Operand ContextOperand(Register context, int index) const { |  | 
| 211     return Operand(context, Context::SlotOffset(index)); |  | 
| 212   } |  | 
| 213 |  | 
| 214   Operand SlotOperand(Slot* slot, Register tmp); |  | 
| 215 |  | 
| 216   void LoadCondition(Expression* x, |  | 
| 217                      TypeofState typeof_state, |  | 
| 218                      Label* true_target, |  | 
| 219                      Label* false_target, |  | 
| 220                      bool force_cc); |  | 
| 221   void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF); |  | 
| 222   void LoadGlobal(); |  | 
| 223 |  | 
| 224   // Read a value from a slot and leave it on top of the expression stack. |  | 
| 225   void LoadFromSlot(Slot* slot, TypeofState typeof_state); |  | 
| 226 |  | 
| 227   // Special code for typeof expressions: Unfortunately, we must |  | 
| 228   // be careful when loading the expression in 'typeof' |  | 
| 229   // expressions. We are not allowed to throw reference errors for |  | 
| 230   // non-existing properties of the global object, so we must make it |  | 
| 231   // look like an explicit property access, instead of an access |  | 
| 232   // through the context chain. |  | 
| 233   void LoadTypeofExpression(Expression* x); |  | 
| 234 |  | 
| 235   void ToBoolean(Label* true_target, Label* false_target); |  | 
| 236 |  | 
| 237   void GenericBinaryOperation( |  | 
| 238       Token::Value op, |  | 
| 239       const OverwriteMode overwrite_mode = NO_OVERWRITE); |  | 
| 240   void Comparison(Condition cc, bool strict = false); |  | 
| 241 |  | 
| 242   // Inline small integer literals. To prevent long attacker-controlled byte |  | 
| 243   // sequences, we only inline small Smi:s. |  | 
| 244   static const int kMaxSmiInlinedBits = 16; |  | 
| 245   bool IsInlineSmi(Literal* literal); |  | 
| 246   void SmiComparison(Condition cc,  Handle<Object> value, bool strict = false); |  | 
| 247   void SmiOperation(Token::Value op, |  | 
| 248                     Handle<Object> value, |  | 
| 249                     bool reversed, |  | 
| 250                     OverwriteMode overwrite_mode); |  | 
| 251 |  | 
| 252   void CallWithArguments(ZoneList<Expression*>* arguments, int position); |  | 
| 253 |  | 
| 254   // Declare global variables and functions in the given array of |  | 
| 255   // name/value pairs. |  | 
| 256   virtual void DeclareGlobals(Handle<FixedArray> pairs); |  | 
| 257 |  | 
| 258   // Instantiate the function boilerplate. |  | 
| 259   void InstantiateBoilerplate(Handle<JSFunction> boilerplate); |  | 
| 260 |  | 
| 261   // Control flow |  | 
| 262   void Branch(bool if_true, Label* L); |  | 
| 263   void CheckStack(); |  | 
| 264   void CleanStack(int num_bytes); |  | 
| 265 |  | 
| 266   // Node visitors |  | 
| 267 #define DEF_VISIT(type)                         \ |  | 
| 268   virtual void Visit##type(type* node); |  | 
| 269   NODE_LIST(DEF_VISIT) |  | 
| 270 #undef DEF_VISIT |  | 
| 271 |  | 
| 272   // Only allow fast-case switch if the range of labels is at most |  | 
| 273   // this factor times the number of case labels. |  | 
| 274   // Value is derived from comparing the size of code generated by the normal |  | 
| 275   // switch code for Smi-labels to the size of a single pointer. If code |  | 
| 276   // quality increases this number should be decreased to match. |  | 
| 277   static const int kFastSwitchMaxOverheadFactor = 5; |  | 
| 278 |  | 
| 279   // Minimal number of switch cases required before we allow jump-table |  | 
| 280   // optimization. |  | 
| 281   static const int kFastSwitchMinCaseCount = 5; |  | 
| 282 |  | 
| 283   virtual int FastCaseSwitchMaxOverheadFactor(); |  | 
| 284   virtual int FastCaseSwitchMinCaseCount(); |  | 
| 285 |  | 
| 286   // Generate a computed jump with an empty jump table. |  | 
| 287   // Binds a label to the start of the jump table. This table must |  | 
| 288   // be populated later when the addresses of the targets are known. |  | 
| 289   // Used by GenerateFastCaseSwitchStatement. |  | 
| 290   virtual void GenerateFastCaseSwitchJumpTable( |  | 
| 291       SwitchStatement* node, int min_index, int range, Label *fail_label, |  | 
| 292       SmartPointer<Label*> &case_targets, SmartPointer<Label> &case_labels); |  | 
| 293 |  | 
| 294   void RecordStatementPosition(Node* node); |  | 
| 295 |  | 
| 296   // Activation frames. |  | 
| 297   void EnterJSFrame(); |  | 
| 298   void ExitJSFrame(); |  | 
| 299 |  | 
| 300   virtual void GenerateIsSmi(ZoneList<Expression*>* args); |  | 
| 301   virtual void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args); |  | 
| 302   virtual void GenerateIsArray(ZoneList<Expression*>* args); |  | 
| 303 |  | 
| 304   virtual void GenerateArgumentsLength(ZoneList<Expression*>* args); |  | 
| 305   virtual void GenerateArgumentsAccess(ZoneList<Expression*>* args); |  | 
| 306 |  | 
| 307   virtual void GenerateValueOf(ZoneList<Expression*>* args); |  | 
| 308   virtual void GenerateSetValueOf(ZoneList<Expression*>* args); |  | 
| 309 |  | 
| 310   virtual void GenerateFastCharCodeAt(ZoneList<Expression*>* args); |  | 
| 311 |  | 
| 312   virtual void GenerateObjectEquals(ZoneList<Expression*>* args); |  | 
| 313 |  | 
| 314   friend class Reference; |  | 
| 315   friend class Property; |  | 
| 316   friend class VariableProxy; |  | 
| 317   friend class Slot; |  | 
| 318 }; |  | 
| 319 |  | 
| 320 |  | 
| 321 // ------------------------------------------------------------------------- | 41 // ------------------------------------------------------------------------- | 
| 322 // CodeGenState implementation. | 42 // CodeGenState implementation. | 
| 323 | 43 | 
| 324 CodeGenState::CodeGenState(Ia32CodeGenerator* owner) | 44 CodeGenState::CodeGenState(CodeGenerator* owner) | 
| 325     : owner_(owner), | 45     : owner_(owner), | 
| 326       typeof_state_(NOT_INSIDE_TYPEOF), | 46       typeof_state_(NOT_INSIDE_TYPEOF), | 
| 327       true_target_(NULL), | 47       true_target_(NULL), | 
| 328       false_target_(NULL), | 48       false_target_(NULL), | 
| 329       previous_(NULL) { | 49       previous_(NULL) { | 
| 330   owner_->set_state(this); | 50   owner_->set_state(this); | 
| 331 } | 51 } | 
| 332 | 52 | 
| 333 | 53 | 
| 334 CodeGenState::CodeGenState(Ia32CodeGenerator* owner, | 54 CodeGenState::CodeGenState(CodeGenerator* owner, | 
| 335                            TypeofState typeof_state, | 55                            TypeofState typeof_state, | 
| 336                            Label* true_target, | 56                            Label* true_target, | 
| 337                            Label* false_target) | 57                            Label* false_target) | 
| 338     : owner_(owner), | 58     : owner_(owner), | 
| 339       typeof_state_(typeof_state), | 59       typeof_state_(typeof_state), | 
| 340       true_target_(true_target), | 60       true_target_(true_target), | 
| 341       false_target_(false_target), | 61       false_target_(false_target), | 
| 342       previous_(owner->state()) { | 62       previous_(owner->state()) { | 
| 343   owner_->set_state(this); | 63   owner_->set_state(this); | 
| 344 } | 64 } | 
| 345 | 65 | 
| 346 | 66 | 
| 347 CodeGenState::~CodeGenState() { | 67 CodeGenState::~CodeGenState() { | 
| 348   ASSERT(owner_->state() == this); | 68   ASSERT(owner_->state() == this); | 
| 349   owner_->set_state(previous_); | 69   owner_->set_state(previous_); | 
| 350 } | 70 } | 
| 351 | 71 | 
| 352 | 72 | 
| 353 // ----------------------------------------------------------------------------- | 73 // ----------------------------------------------------------------------------- | 
| 354 // Ia32CodeGenerator implementation | 74 // CodeGenerator implementation | 
| 355 | 75 | 
| 356 #define __ masm_-> | 76 #define __ masm_-> | 
| 357 | 77 | 
| 358 Handle<Code> Ia32CodeGenerator::MakeCode(FunctionLiteral* flit, | 78 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script, | 
| 359                                          Handle<Script> script, | 79                              bool is_eval) | 
| 360                                          bool is_eval) { | 80     : is_eval_(is_eval), | 
| 361 #ifdef ENABLE_DISASSEMBLER | 81       script_(script), | 
| 362   bool print_code = FLAG_print_code && !Bootstrapper::IsActive(); | 82       deferred_(8), | 
| 363 #endif |  | 
| 364 |  | 
| 365 #ifdef DEBUG |  | 
| 366   bool print_source = false; |  | 
| 367   bool print_ast = false; |  | 
| 368   const char* ftype; |  | 
| 369 |  | 
| 370   if (Bootstrapper::IsActive()) { |  | 
| 371     print_source = FLAG_print_builtin_source; |  | 
| 372     print_ast = FLAG_print_builtin_ast; |  | 
| 373     print_code = FLAG_print_builtin_code; |  | 
| 374     ftype = "builtin"; |  | 
| 375   } else { |  | 
| 376     print_source = FLAG_print_source; |  | 
| 377     print_ast = FLAG_print_ast; |  | 
| 378     ftype = "user-defined"; |  | 
| 379   } |  | 
| 380 |  | 
| 381   if (FLAG_trace_codegen || print_source || print_ast) { |  | 
| 382     PrintF("*** Generate code for %s function: ", ftype); |  | 
| 383     flit->name()->ShortPrint(); |  | 
| 384     PrintF(" ***\n"); |  | 
| 385   } |  | 
| 386 |  | 
| 387   if (print_source) { |  | 
| 388     PrintF("--- Source from AST ---\n%s\n", PrettyPrinter().PrintProgram(flit)); |  | 
| 389   } |  | 
| 390 |  | 
| 391   if (print_ast) { |  | 
| 392     PrintF("--- AST ---\n%s\n", AstPrinter().PrintProgram(flit)); |  | 
| 393   } |  | 
| 394 #endif  // DEBUG |  | 
| 395 |  | 
| 396   // Generate code. |  | 
| 397   const int initial_buffer_size = 4 * KB; |  | 
| 398   Ia32CodeGenerator cgen(initial_buffer_size, script, is_eval); |  | 
| 399   cgen.GenCode(flit); |  | 
| 400   if (cgen.HasStackOverflow()) { |  | 
| 401     ASSERT(!Top::has_pending_exception()); |  | 
| 402     return Handle<Code>::null(); |  | 
| 403   } |  | 
| 404 |  | 
| 405   // Process any deferred code. |  | 
| 406   cgen.ProcessDeferred(); |  | 
| 407 |  | 
| 408   // Allocate and install the code. |  | 
| 409   CodeDesc desc; |  | 
| 410   cgen.masm()->GetCode(&desc); |  | 
| 411   ScopeInfo<> sinfo(flit->scope()); |  | 
| 412   Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); |  | 
| 413   Handle<Code> code = Factory::NewCode(desc, &sinfo, flags); |  | 
| 414 |  | 
| 415   // Add unresolved entries in the code to the fixup list. |  | 
| 416   Bootstrapper::AddFixup(*code, cgen.masm()); |  | 
| 417 |  | 
| 418 #ifdef ENABLE_DISASSEMBLER |  | 
| 419   if (print_code) { |  | 
| 420     // Print the source code if available. |  | 
| 421     if (!script->IsUndefined() && !script->source()->IsUndefined()) { |  | 
| 422       PrintF("--- Raw source ---\n"); |  | 
| 423       StringInputBuffer stream(String::cast(script->source())); |  | 
| 424       stream.Seek(flit->start_position()); |  | 
| 425       // flit->end_position() points to the last character in the stream. We |  | 
| 426       // need to compensate by adding one to calculate the length. |  | 
| 427       int source_len = flit->end_position() - flit->start_position() + 1; |  | 
| 428       for (int i = 0; i < source_len; i++) { |  | 
| 429         if (stream.has_more()) PrintF("%c", stream.GetNext()); |  | 
| 430       } |  | 
| 431       PrintF("\n\n"); |  | 
| 432     } |  | 
| 433     PrintF("--- Code ---\n"); |  | 
| 434     code->Disassemble(); |  | 
| 435   } |  | 
| 436 #endif  // ENABLE_DISASSEMBLER |  | 
| 437 |  | 
| 438   return code; |  | 
| 439 } |  | 
| 440 |  | 
| 441 |  | 
| 442 Ia32CodeGenerator::Ia32CodeGenerator(int buffer_size, |  | 
| 443                                      Handle<Script> script, |  | 
| 444                                      bool is_eval) |  | 
| 445     : CodeGenerator(is_eval, script), |  | 
| 446       masm_(new MacroAssembler(NULL, buffer_size)), | 83       masm_(new MacroAssembler(NULL, buffer_size)), | 
| 447       scope_(NULL), | 84       scope_(NULL), | 
| 448       cc_reg_(no_condition), | 85       cc_reg_(no_condition), | 
| 449       state_(NULL), | 86       state_(NULL), | 
| 450       is_inside_try_(false), | 87       is_inside_try_(false), | 
| 451       break_stack_height_(0) { | 88       break_stack_height_(0) { | 
| 452 } | 89 } | 
| 453 | 90 | 
| 454 | 91 | 
| 455 // Calling conventions: | 92 // Calling conventions: | 
| 456 // ebp: frame pointer | 93 // ebp: frame pointer | 
| 457 // esp: stack pointer | 94 // esp: stack pointer | 
| 458 // edi: caller's parameter pointer | 95 // edi: caller's parameter pointer | 
| 459 // esi: callee's context | 96 // esi: callee's context | 
| 460 | 97 | 
| 461 void Ia32CodeGenerator::GenCode(FunctionLiteral* fun) { | 98 void CodeGenerator::GenCode(FunctionLiteral* fun) { | 
| 462   // Record the position for debugging purposes. | 99   // Record the position for debugging purposes. | 
| 463   __ RecordPosition(fun->start_position()); | 100   __ RecordPosition(fun->start_position()); | 
| 464 | 101 | 
| 465   Scope* scope = fun->scope(); | 102   Scope* scope = fun->scope(); | 
| 466   ZoneList<Statement*>* body = fun->body(); | 103   ZoneList<Statement*>* body = fun->body(); | 
| 467 | 104 | 
| 468   // Initialize state. | 105   // Initialize state. | 
| 469   { CodeGenState state(this); | 106   { CodeGenState state(this); | 
| 470     scope_ = scope; | 107     scope_ = scope; | 
| 471     cc_reg_ = no_condition; | 108     cc_reg_ = no_condition; | 
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 662     } | 299     } | 
| 663   } | 300   } | 
| 664 | 301 | 
| 665   // Code generation state must be reset. | 302   // Code generation state must be reset. | 
| 666   scope_ = NULL; | 303   scope_ = NULL; | 
| 667   ASSERT(!has_cc()); | 304   ASSERT(!has_cc()); | 
| 668   ASSERT(state_ == NULL); | 305   ASSERT(state_ == NULL); | 
| 669 } | 306 } | 
| 670 | 307 | 
| 671 | 308 | 
| 672 Operand Ia32CodeGenerator::SlotOperand(Slot* slot, Register tmp) { | 309 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { | 
| 673   // Currently, this assertion will fail if we try to assign to | 310   // Currently, this assertion will fail if we try to assign to | 
| 674   // a constant variable that is constant because it is read-only | 311   // a constant variable that is constant because it is read-only | 
| 675   // (such as the variable referring to a named function expression). | 312   // (such as the variable referring to a named function expression). | 
| 676   // We need to implement assignments to read-only variables. | 313   // We need to implement assignments to read-only variables. | 
| 677   // Ideally, we should do this during AST generation (by converting | 314   // Ideally, we should do this during AST generation (by converting | 
| 678   // such assignments into expression statements); however, in general | 315   // such assignments into expression statements); however, in general | 
| 679   // we may not be able to make the decision until past AST generation, | 316   // we may not be able to make the decision until past AST generation, | 
| 680   // that is when the entire program is known. | 317   // that is when the entire program is known. | 
| 681   ASSERT(slot != NULL); | 318   ASSERT(slot != NULL); | 
| 682   int index = slot->index(); | 319   int index = slot->index(); | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 721       return Operand(eax); | 358       return Operand(eax); | 
| 722   } | 359   } | 
| 723 } | 360 } | 
| 724 | 361 | 
| 725 | 362 | 
| 726 // Loads a value on TOS. If it is a boolean value, the result may have been | 363 // Loads a value on TOS. If it is a boolean value, the result may have been | 
| 727 // (partially) translated into branches, or it may have set the condition code | 364 // (partially) translated into branches, or it may have set the condition code | 
| 728 // register. If force_cc is set, the value is forced to set the condition code | 365 // register. If force_cc is set, the value is forced to set the condition code | 
| 729 // register and no value is pushed. If the condition code register was set, | 366 // register and no value is pushed. If the condition code register was set, | 
| 730 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. | 367 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. | 
| 731 void Ia32CodeGenerator::LoadCondition(Expression* x, | 368 void CodeGenerator::LoadCondition(Expression* x, | 
| 732                                       TypeofState typeof_state, | 369                                   TypeofState typeof_state, | 
| 733                                       Label* true_target, | 370                                   Label* true_target, | 
| 734                                       Label* false_target, | 371                                   Label* false_target, | 
| 735                                       bool force_cc) { | 372                                   bool force_cc) { | 
| 736   ASSERT(!has_cc()); | 373   ASSERT(!has_cc()); | 
| 737 | 374 | 
| 738   { CodeGenState new_state(this, typeof_state, true_target, false_target); | 375   { CodeGenState new_state(this, typeof_state, true_target, false_target); | 
| 739     Visit(x); | 376     Visit(x); | 
| 740   } | 377   } | 
| 741   if (force_cc && !has_cc()) { | 378   if (force_cc && !has_cc()) { | 
| 742     ToBoolean(true_target, false_target); | 379     ToBoolean(true_target, false_target); | 
| 743   } | 380   } | 
| 744   ASSERT(has_cc() || !force_cc); | 381   ASSERT(has_cc() || !force_cc); | 
| 745 } | 382 } | 
| 746 | 383 | 
| 747 | 384 | 
| 748 void Ia32CodeGenerator::Load(Expression* x, TypeofState typeof_state) { | 385 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { | 
| 749   Label true_target; | 386   Label true_target; | 
| 750   Label false_target; | 387   Label false_target; | 
| 751   LoadCondition(x, typeof_state, &true_target, &false_target, false); | 388   LoadCondition(x, typeof_state, &true_target, &false_target, false); | 
| 752 | 389 | 
| 753   if (has_cc()) { | 390   if (has_cc()) { | 
| 754     // convert cc_reg_ into a bool | 391     // convert cc_reg_ into a bool | 
| 755 | 392 | 
| 756     Label loaded, materialize_true; | 393     Label loaded, materialize_true; | 
| 757     __ j(cc_reg_, &materialize_true); | 394     __ j(cc_reg_, &materialize_true); | 
| 758     __ push(Immediate(Factory::false_value())); | 395     __ push(Immediate(Factory::false_value())); | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
| 784       __ bind(&false_target); | 421       __ bind(&false_target); | 
| 785       __ push(Immediate(Factory::false_value())); | 422       __ push(Immediate(Factory::false_value())); | 
| 786     } | 423     } | 
| 787     // everything is loaded at this point | 424     // everything is loaded at this point | 
| 788     __ bind(&loaded); | 425     __ bind(&loaded); | 
| 789   } | 426   } | 
| 790   ASSERT(!has_cc()); | 427   ASSERT(!has_cc()); | 
| 791 } | 428 } | 
| 792 | 429 | 
| 793 | 430 | 
| 794 void Ia32CodeGenerator::LoadGlobal() { | 431 void CodeGenerator::LoadGlobal() { | 
| 795   __ push(GlobalObject()); | 432   __ push(GlobalObject()); | 
| 796 } | 433 } | 
| 797 | 434 | 
| 798 | 435 | 
| 799 // TODO(1241834): Get rid of this function in favor of just using Load, now | 436 // TODO(1241834): Get rid of this function in favor of just using Load, now | 
| 800 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global | 437 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global | 
| 801 // variables w/o reference errors elsewhere. | 438 // variables w/o reference errors elsewhere. | 
| 802 void Ia32CodeGenerator::LoadTypeofExpression(Expression* x) { | 439 void CodeGenerator::LoadTypeofExpression(Expression* x) { | 
| 803   Variable* variable = x->AsVariableProxy()->AsVariable(); | 440   Variable* variable = x->AsVariableProxy()->AsVariable(); | 
| 804   if (variable != NULL && !variable->is_this() && variable->is_global()) { | 441   if (variable != NULL && !variable->is_this() && variable->is_global()) { | 
| 805     // NOTE: This is somewhat nasty. We force the compiler to load | 442     // NOTE: This is somewhat nasty. We force the compiler to load | 
| 806     // the variable as if through '<global>.<variable>' to make sure we | 443     // the variable as if through '<global>.<variable>' to make sure we | 
| 807     // do not get reference errors. | 444     // do not get reference errors. | 
| 808     Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); | 445     Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); | 
| 809     Literal key(variable->name()); | 446     Literal key(variable->name()); | 
| 810     // TODO(1241834): Fetch the position from the variable instead of using | 447     // TODO(1241834): Fetch the position from the variable instead of using | 
| 811     // no position. | 448     // no position. | 
| 812     Property property(&global, &key, RelocInfo::kNoPosition); | 449     Property property(&global, &key, RelocInfo::kNoPosition); | 
| 813     Load(&property); | 450     Load(&property); | 
| 814   } else { | 451   } else { | 
| 815     Load(x, INSIDE_TYPEOF); | 452     Load(x, INSIDE_TYPEOF); | 
| 816   } | 453   } | 
| 817 } | 454 } | 
| 818 | 455 | 
| 819 | 456 | 
| 820 Reference::Reference(Ia32CodeGenerator* cgen, Expression* expression) | 457 Reference::Reference(CodeGenerator* cgen, Expression* expression) | 
| 821     : cgen_(cgen), expression_(expression), type_(ILLEGAL) { | 458     : cgen_(cgen), expression_(expression), type_(ILLEGAL) { | 
| 822   cgen->LoadReference(this); | 459   cgen->LoadReference(this); | 
| 823 } | 460 } | 
| 824 | 461 | 
| 825 | 462 | 
| 826 Reference::~Reference() { | 463 Reference::~Reference() { | 
| 827   cgen_->UnloadReference(this); | 464   cgen_->UnloadReference(this); | 
| 828 } | 465 } | 
| 829 | 466 | 
| 830 | 467 | 
| 831 void Ia32CodeGenerator::LoadReference(Reference* ref) { | 468 void CodeGenerator::LoadReference(Reference* ref) { | 
| 832   Comment cmnt(masm_, "[ LoadReference"); | 469   Comment cmnt(masm_, "[ LoadReference"); | 
| 833   Expression* e = ref->expression(); | 470   Expression* e = ref->expression(); | 
| 834   Property* property = e->AsProperty(); | 471   Property* property = e->AsProperty(); | 
| 835   Variable* var = e->AsVariableProxy()->AsVariable(); | 472   Variable* var = e->AsVariableProxy()->AsVariable(); | 
| 836 | 473 | 
| 837   if (property != NULL) { | 474   if (property != NULL) { | 
| 838     // The expression is either a property or a variable proxy that rewrites | 475     // The expression is either a property or a variable proxy that rewrites | 
| 839     // to a property. | 476     // to a property. | 
| 840     Load(property->obj()); | 477     Load(property->obj()); | 
| 841     // We use a named reference if the key is a literal symbol, unless it is | 478     // We use a named reference if the key is a literal symbol, unless it is | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 863       ref->set_type(Reference::SLOT); | 500       ref->set_type(Reference::SLOT); | 
| 864     } | 501     } | 
| 865   } else { | 502   } else { | 
| 866     // Anything else is a runtime error. | 503     // Anything else is a runtime error. | 
| 867     Load(e); | 504     Load(e); | 
| 868     __ CallRuntime(Runtime::kThrowReferenceError, 1); | 505     __ CallRuntime(Runtime::kThrowReferenceError, 1); | 
| 869   } | 506   } | 
| 870 } | 507 } | 
| 871 | 508 | 
| 872 | 509 | 
| 873 void Ia32CodeGenerator::UnloadReference(Reference* ref) { | 510 void CodeGenerator::UnloadReference(Reference* ref) { | 
| 874   // Pop a reference from the stack while preserving TOS. | 511   // Pop a reference from the stack while preserving TOS. | 
| 875   Comment cmnt(masm_, "[ UnloadReference"); | 512   Comment cmnt(masm_, "[ UnloadReference"); | 
| 876   int size = ref->size(); | 513   int size = ref->size(); | 
| 877   if (size <= 0) { | 514   if (size <= 0) { | 
| 878     // Do nothing. No popping is necessary. | 515     // Do nothing. No popping is necessary. | 
| 879   } else if (size == 1) { | 516   } else if (size == 1) { | 
| 880     __ pop(eax); | 517     __ pop(eax); | 
| 881     __ mov(TOS, eax); | 518     __ mov(TOS, eax); | 
| 882   } else { | 519   } else { | 
| 883     __ pop(eax); | 520     __ pop(eax); | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 895 | 532 | 
| 896  private: | 533  private: | 
| 897   Major MajorKey() { return ToBoolean; } | 534   Major MajorKey() { return ToBoolean; } | 
| 898   int MinorKey() { return 0; } | 535   int MinorKey() { return 0; } | 
| 899 }; | 536 }; | 
| 900 | 537 | 
| 901 | 538 | 
| 902 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and | 539 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and | 
| 903 // convert it to a boolean in the condition code register or jump to | 540 // convert it to a boolean in the condition code register or jump to | 
| 904 // 'false_target'/'true_target' as appropriate. | 541 // 'false_target'/'true_target' as appropriate. | 
| 905 void Ia32CodeGenerator::ToBoolean(Label* true_target, Label* false_target) { | 542 void CodeGenerator::ToBoolean(Label* true_target, Label* false_target) { | 
| 906   Comment cmnt(masm_, "[ ToBoolean"); | 543   Comment cmnt(masm_, "[ ToBoolean"); | 
| 907 | 544 | 
| 908   // The value to convert should be popped from the stack. | 545   // The value to convert should be popped from the stack. | 
| 909   __ pop(eax); | 546   __ pop(eax); | 
| 910 | 547 | 
| 911   // Fast case checks. | 548   // Fast case checks. | 
| 912 | 549 | 
| 913   // 'false' => false. | 550   // 'false' => false. | 
| 914   __ cmp(eax, Factory::false_value()); | 551   __ cmp(eax, Factory::false_value()); | 
| 915   __ j(equal, false_target); | 552   __ j(equal, false_target); | 
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1006   case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND"; | 643   case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND"; | 
| 1007   case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR"; | 644   case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR"; | 
| 1008   case Token::SAR: return "GenericBinaryOpStub_SAR"; | 645   case Token::SAR: return "GenericBinaryOpStub_SAR"; | 
| 1009   case Token::SHL: return "GenericBinaryOpStub_SHL"; | 646   case Token::SHL: return "GenericBinaryOpStub_SHL"; | 
| 1010   case Token::SHR: return "GenericBinaryOpStub_SHR"; | 647   case Token::SHR: return "GenericBinaryOpStub_SHR"; | 
| 1011   default:         return "GenericBinaryOpStub"; | 648   default:         return "GenericBinaryOpStub"; | 
| 1012   } | 649   } | 
| 1013 } | 650 } | 
| 1014 | 651 | 
| 1015 | 652 | 
| 1016 void Ia32CodeGenerator::GenericBinaryOperation(Token::Value op, | 653 void CodeGenerator::GenericBinaryOperation(Token::Value op, | 
| 1017                                                OverwriteMode overwrite_mode) { | 654                                                OverwriteMode overwrite_mode) { | 
| 1018   Comment cmnt(masm_, "[ BinaryOperation"); | 655   Comment cmnt(masm_, "[ BinaryOperation"); | 
| 1019   Comment cmnt_token(masm_, Token::String(op)); | 656   Comment cmnt_token(masm_, Token::String(op)); | 
| 1020   switch (op) { | 657   switch (op) { | 
| 1021     case Token::ADD: | 658     case Token::ADD: | 
| 1022     case Token::SUB: | 659     case Token::SUB: | 
| 1023     case Token::MUL: | 660     case Token::MUL: | 
| 1024     case Token::DIV: | 661     case Token::DIV: | 
| 1025     case Token::MOD: { | 662     case Token::MOD: { | 
| 1026       GenericBinaryOpStub stub(op, overwrite_mode); | 663       GenericBinaryOpStub stub(op, overwrite_mode); | 
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1263     GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_); | 900     GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_); | 
| 1264     __ CallStub(&igostub); | 901     __ CallStub(&igostub); | 
| 1265   } | 902   } | 
| 1266 | 903 | 
| 1267  private: | 904  private: | 
| 1268   Register tos_reg_; | 905   Register tos_reg_; | 
| 1269   OverwriteMode overwrite_mode_; | 906   OverwriteMode overwrite_mode_; | 
| 1270 }; | 907 }; | 
| 1271 | 908 | 
| 1272 | 909 | 
| 1273 void Ia32CodeGenerator::SmiOperation(Token::Value op, | 910 void CodeGenerator::SmiOperation(Token::Value op, | 
| 1274                                      Handle<Object> value, | 911                                      Handle<Object> value, | 
| 1275                                      bool reversed, | 912                                      bool reversed, | 
| 1276                                      OverwriteMode overwrite_mode) { | 913                                      OverwriteMode overwrite_mode) { | 
| 1277   // NOTE: This is an attempt to inline (a bit) more of the code for | 914   // NOTE: This is an attempt to inline (a bit) more of the code for | 
| 1278   // some possible smi operations (like + and -) when (at least) one | 915   // some possible smi operations (like + and -) when (at least) one | 
| 1279   // of the operands is a literal smi. With this optimization, the | 916   // of the operands is a literal smi. With this optimization, the | 
| 1280   // performance of the system is increased by ~15%, and the generated | 917   // performance of the system is increased by ~15%, and the generated | 
| 1281   // code size is increased by ~1% (measured on a combination of | 918   // code size is increased by ~1% (measured on a combination of | 
| 1282   // different benchmarks). | 919   // different benchmarks). | 
| 1283 | 920 | 
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1469 #ifdef DEBUG | 1106 #ifdef DEBUG | 
| 1470   void Print() { | 1107   void Print() { | 
| 1471     PrintF("CompareStub (cc %d), (strict %s)\n", | 1108     PrintF("CompareStub (cc %d), (strict %s)\n", | 
| 1472            static_cast<int>(cc_), | 1109            static_cast<int>(cc_), | 
| 1473            strict_ ? "true" : "false"); | 1110            strict_ ? "true" : "false"); | 
| 1474   } | 1111   } | 
| 1475 #endif | 1112 #endif | 
| 1476 }; | 1113 }; | 
| 1477 | 1114 | 
| 1478 | 1115 | 
| 1479 void Ia32CodeGenerator::Comparison(Condition cc, bool strict) { | 1116 void CodeGenerator::Comparison(Condition cc, bool strict) { | 
| 1480   // Strict only makes sense for equality comparisons. | 1117   // Strict only makes sense for equality comparisons. | 
| 1481   ASSERT(!strict || cc == equal); | 1118   ASSERT(!strict || cc == equal); | 
| 1482 | 1119 | 
| 1483   // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. | 1120   // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. | 
| 1484   if (cc == greater || cc == less_equal) { | 1121   if (cc == greater || cc == less_equal) { | 
| 1485     cc = ReverseCondition(cc); | 1122     cc = ReverseCondition(cc); | 
| 1486     __ pop(edx); | 1123     __ pop(edx); | 
| 1487     __ pop(eax); | 1124     __ pop(eax); | 
| 1488   } else { | 1125   } else { | 
| 1489     __ pop(eax); | 1126     __ pop(eax); | 
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1536   CompareStub stub(cc_, strict_); | 1173   CompareStub stub(cc_, strict_); | 
| 1537   // Setup parameters and call stub. | 1174   // Setup parameters and call stub. | 
| 1538   __ mov(edx, Operand(eax)); | 1175   __ mov(edx, Operand(eax)); | 
| 1539   __ mov(Operand(eax), Immediate(Smi::FromInt(value_))); | 1176   __ mov(Operand(eax), Immediate(Smi::FromInt(value_))); | 
| 1540   __ CallStub(&stub); | 1177   __ CallStub(&stub); | 
| 1541   __ cmp(eax, 0); | 1178   __ cmp(eax, 0); | 
| 1542   // "result" is returned in the flags | 1179   // "result" is returned in the flags | 
| 1543 } | 1180 } | 
| 1544 | 1181 | 
| 1545 | 1182 | 
| 1546 void Ia32CodeGenerator::SmiComparison(Condition cc, | 1183 void CodeGenerator::SmiComparison(Condition cc, | 
| 1547                                       Handle<Object> value, | 1184                                       Handle<Object> value, | 
| 1548                                       bool strict) { | 1185                                       bool strict) { | 
| 1549   // Strict only makes sense for equality comparisons. | 1186   // Strict only makes sense for equality comparisons. | 
| 1550   ASSERT(!strict || cc == equal); | 1187   ASSERT(!strict || cc == equal); | 
| 1551 | 1188 | 
| 1552   int int_value = Smi::cast(*value)->value(); | 1189   int int_value = Smi::cast(*value)->value(); | 
| 1553   ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); | 1190   ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); | 
| 1554 | 1191 | 
| 1555   SmiComparisonDeferred* deferred = | 1192   SmiComparisonDeferred* deferred = | 
| 1556       new SmiComparisonDeferred(this, cc, strict, int_value); | 1193       new SmiComparisonDeferred(this, cc, strict, int_value); | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 1577   void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); } | 1214   void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); } | 
| 1578 #endif | 1215 #endif | 
| 1579 | 1216 | 
| 1580   Major MajorKey() { return CallFunction; } | 1217   Major MajorKey() { return CallFunction; } | 
| 1581   int MinorKey() { return argc_; } | 1218   int MinorKey() { return argc_; } | 
| 1582 }; | 1219 }; | 
| 1583 | 1220 | 
| 1584 | 1221 | 
| 1585 // Call the function just below TOS on the stack with the given | 1222 // Call the function just below TOS on the stack with the given | 
| 1586 // arguments. The receiver is the TOS. | 1223 // arguments. The receiver is the TOS. | 
| 1587 void Ia32CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, | 1224 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, | 
| 1588                                           int position) { | 1225                                           int position) { | 
| 1589   // Push the arguments ("left-to-right") on the stack. | 1226   // Push the arguments ("left-to-right") on the stack. | 
| 1590   for (int i = 0; i < args->length(); i++) { | 1227   for (int i = 0; i < args->length(); i++) { | 
| 1591     Load(args->at(i)); | 1228     Load(args->at(i)); | 
| 1592   } | 1229   } | 
| 1593 | 1230 | 
| 1594   // Record the position for debugging purposes. | 1231   // Record the position for debugging purposes. | 
| 1595   __ RecordPosition(position); | 1232   __ RecordPosition(position); | 
| 1596 | 1233 | 
| 1597   // Use the shared code stub to call the function. | 1234   // Use the shared code stub to call the function. | 
| 1598   CallFunctionStub call_function(args->length()); | 1235   CallFunctionStub call_function(args->length()); | 
| 1599   __ CallStub(&call_function); | 1236   __ CallStub(&call_function); | 
| 1600 | 1237 | 
| 1601   // Restore context and pop function from the stack. | 1238   // Restore context and pop function from the stack. | 
| 1602   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1239   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 
| 1603   __ mov(TOS, eax); | 1240   __ mov(TOS, eax); | 
| 1604 } | 1241 } | 
| 1605 | 1242 | 
| 1606 | 1243 | 
| 1607 void Ia32CodeGenerator::Branch(bool if_true, Label* L) { | 1244 void CodeGenerator::Branch(bool if_true, Label* L) { | 
| 1608   ASSERT(has_cc()); | 1245   ASSERT(has_cc()); | 
| 1609   Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); | 1246   Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); | 
| 1610   __ j(cc, L); | 1247   __ j(cc, L); | 
| 1611   cc_reg_ = no_condition; | 1248   cc_reg_ = no_condition; | 
| 1612 } | 1249 } | 
| 1613 | 1250 | 
| 1614 | 1251 | 
| 1615 void Ia32CodeGenerator::CheckStack() { | 1252 void CodeGenerator::CheckStack() { | 
| 1616   if (FLAG_check_stack) { | 1253   if (FLAG_check_stack) { | 
| 1617     Label stack_is_ok; | 1254     Label stack_is_ok; | 
| 1618     StackCheckStub stub; | 1255     StackCheckStub stub; | 
| 1619     ExternalReference stack_guard_limit = | 1256     ExternalReference stack_guard_limit = | 
| 1620         ExternalReference::address_of_stack_guard_limit(); | 1257         ExternalReference::address_of_stack_guard_limit(); | 
| 1621     __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); | 1258     __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); | 
| 1622     __ j(above_equal, &stack_is_ok, taken); | 1259     __ j(above_equal, &stack_is_ok, taken); | 
| 1623     __ CallStub(&stub); | 1260     __ CallStub(&stub); | 
| 1624     __ bind(&stack_is_ok); | 1261     __ bind(&stack_is_ok); | 
| 1625   } | 1262   } | 
| 1626 } | 1263 } | 
| 1627 | 1264 | 
| 1628 | 1265 | 
| 1629 void Ia32CodeGenerator::VisitBlock(Block* node) { | 1266 void CodeGenerator::VisitBlock(Block* node) { | 
| 1630   Comment cmnt(masm_, "[ Block"); | 1267   Comment cmnt(masm_, "[ Block"); | 
| 1631   RecordStatementPosition(node); | 1268   RecordStatementPosition(node); | 
| 1632   node->set_break_stack_height(break_stack_height_); | 1269   node->set_break_stack_height(break_stack_height_); | 
| 1633   VisitStatements(node->statements()); | 1270   VisitStatements(node->statements()); | 
| 1634   __ bind(node->break_target()); | 1271   __ bind(node->break_target()); | 
| 1635 } | 1272 } | 
| 1636 | 1273 | 
| 1637 | 1274 | 
| 1638 void Ia32CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 1275 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 
| 1639   __ push(Immediate(pairs)); | 1276   __ push(Immediate(pairs)); | 
| 1640   __ push(Operand(esi)); | 1277   __ push(Operand(esi)); | 
| 1641   __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); | 1278   __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); | 
| 1642   __ CallRuntime(Runtime::kDeclareGlobals, 3); | 1279   __ CallRuntime(Runtime::kDeclareGlobals, 3); | 
| 1643   // Return value is ignored. | 1280   // Return value is ignored. | 
| 1644 } | 1281 } | 
| 1645 | 1282 | 
| 1646 | 1283 | 
| 1647 void Ia32CodeGenerator::VisitDeclaration(Declaration* node) { | 1284 void CodeGenerator::VisitDeclaration(Declaration* node) { | 
| 1648   Comment cmnt(masm_, "[ Declaration"); | 1285   Comment cmnt(masm_, "[ Declaration"); | 
| 1649   Variable* var = node->proxy()->var(); | 1286   Variable* var = node->proxy()->var(); | 
| 1650   ASSERT(var != NULL);  // must have been resolved | 1287   ASSERT(var != NULL);  // must have been resolved | 
| 1651   Slot* slot = var->slot(); | 1288   Slot* slot = var->slot(); | 
| 1652 | 1289 | 
| 1653   // If it was not possible to allocate the variable at compile time, | 1290   // If it was not possible to allocate the variable at compile time, | 
| 1654   // we need to "declare" it at runtime to make sure it actually | 1291   // we need to "declare" it at runtime to make sure it actually | 
| 1655   // exists in the local context. | 1292   // exists in the local context. | 
| 1656   if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1293   if (slot != NULL && slot->type() == Slot::LOOKUP) { | 
| 1657     // Variables with a "LOOKUP" slot were introduced as non-locals | 1294     // Variables with a "LOOKUP" slot were introduced as non-locals | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1698     target.SetValue(NOT_CONST_INIT); | 1335     target.SetValue(NOT_CONST_INIT); | 
| 1699     // Get rid of the assigned value (declarations are statements).  It's | 1336     // Get rid of the assigned value (declarations are statements).  It's | 
| 1700     // safe to pop the value lying on top of the reference before unloading | 1337     // safe to pop the value lying on top of the reference before unloading | 
| 1701     // the reference itself (which preserves the top of stack) because we | 1338     // the reference itself (which preserves the top of stack) because we | 
| 1702     // know that it is a zero-sized reference. | 1339     // know that it is a zero-sized reference. | 
| 1703     __ pop(eax);  // Pop(no_reg); | 1340     __ pop(eax);  // Pop(no_reg); | 
| 1704   } | 1341   } | 
| 1705 } | 1342 } | 
| 1706 | 1343 | 
| 1707 | 1344 | 
| 1708 void Ia32CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { | 1345 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { | 
| 1709   Comment cmnt(masm_, "[ ExpressionStatement"); | 1346   Comment cmnt(masm_, "[ ExpressionStatement"); | 
| 1710   RecordStatementPosition(node); | 1347   RecordStatementPosition(node); | 
| 1711   Expression* expression = node->expression(); | 1348   Expression* expression = node->expression(); | 
| 1712   expression->MarkAsStatement(); | 1349   expression->MarkAsStatement(); | 
| 1713   Load(expression); | 1350   Load(expression); | 
| 1714   __ pop(eax);  // remove the lingering expression result from the top of stack | 1351   __ pop(eax);  // remove the lingering expression result from the top of stack | 
| 1715 } | 1352 } | 
| 1716 | 1353 | 
| 1717 | 1354 | 
| 1718 void Ia32CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { | 1355 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { | 
| 1719   Comment cmnt(masm_, "// EmptyStatement"); | 1356   Comment cmnt(masm_, "// EmptyStatement"); | 
| 1720   // nothing to do | 1357   // nothing to do | 
| 1721 } | 1358 } | 
| 1722 | 1359 | 
| 1723 | 1360 | 
| 1724 void Ia32CodeGenerator::VisitIfStatement(IfStatement* node) { | 1361 void CodeGenerator::VisitIfStatement(IfStatement* node) { | 
| 1725   Comment cmnt(masm_, "[ IfStatement"); | 1362   Comment cmnt(masm_, "[ IfStatement"); | 
| 1726   // Generate different code depending on which | 1363   // Generate different code depending on which | 
| 1727   // parts of the if statement are present or not. | 1364   // parts of the if statement are present or not. | 
| 1728   bool has_then_stm = node->HasThenStatement(); | 1365   bool has_then_stm = node->HasThenStatement(); | 
| 1729   bool has_else_stm = node->HasElseStatement(); | 1366   bool has_else_stm = node->HasElseStatement(); | 
| 1730 | 1367 | 
| 1731   RecordStatementPosition(node); | 1368   RecordStatementPosition(node); | 
| 1732   Label exit; | 1369   Label exit; | 
| 1733   if (has_then_stm && has_else_stm) { | 1370   if (has_then_stm && has_else_stm) { | 
| 1734     Label then; | 1371     Label then; | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1775       // Pop it again, since it is not going to be used. | 1412       // Pop it again, since it is not going to be used. | 
| 1776       __ pop(eax); | 1413       __ pop(eax); | 
| 1777     } | 1414     } | 
| 1778   } | 1415   } | 
| 1779 | 1416 | 
| 1780   // end | 1417   // end | 
| 1781   __ bind(&exit); | 1418   __ bind(&exit); | 
| 1782 } | 1419 } | 
| 1783 | 1420 | 
| 1784 | 1421 | 
| 1785 void Ia32CodeGenerator::CleanStack(int num_bytes) { | 1422 void CodeGenerator::CleanStack(int num_bytes) { | 
| 1786   ASSERT(num_bytes >= 0); | 1423   ASSERT(num_bytes >= 0); | 
| 1787   if (num_bytes > 0) { | 1424   if (num_bytes > 0) { | 
| 1788     __ add(Operand(esp), Immediate(num_bytes)); | 1425     __ add(Operand(esp), Immediate(num_bytes)); | 
| 1789   } | 1426   } | 
| 1790 } | 1427 } | 
| 1791 | 1428 | 
| 1792 | 1429 | 
| 1793 void Ia32CodeGenerator::VisitContinueStatement(ContinueStatement* node) { | 1430 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { | 
| 1794   Comment cmnt(masm_, "[ ContinueStatement"); | 1431   Comment cmnt(masm_, "[ ContinueStatement"); | 
| 1795   RecordStatementPosition(node); | 1432   RecordStatementPosition(node); | 
| 1796   CleanStack(break_stack_height_ - node->target()->break_stack_height()); | 1433   CleanStack(break_stack_height_ - node->target()->break_stack_height()); | 
| 1797   __ jmp(node->target()->continue_target()); | 1434   __ jmp(node->target()->continue_target()); | 
| 1798 } | 1435 } | 
| 1799 | 1436 | 
| 1800 | 1437 | 
| 1801 void Ia32CodeGenerator::VisitBreakStatement(BreakStatement* node) { | 1438 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { | 
| 1802   Comment cmnt(masm_, "[ BreakStatement"); | 1439   Comment cmnt(masm_, "[ BreakStatement"); | 
| 1803   RecordStatementPosition(node); | 1440   RecordStatementPosition(node); | 
| 1804   CleanStack(break_stack_height_ - node->target()->break_stack_height()); | 1441   CleanStack(break_stack_height_ - node->target()->break_stack_height()); | 
| 1805   __ jmp(node->target()->break_target()); | 1442   __ jmp(node->target()->break_target()); | 
| 1806 } | 1443 } | 
| 1807 | 1444 | 
| 1808 | 1445 | 
| 1809 void Ia32CodeGenerator::VisitReturnStatement(ReturnStatement* node) { | 1446 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { | 
| 1810   Comment cmnt(masm_, "[ ReturnStatement"); | 1447   Comment cmnt(masm_, "[ ReturnStatement"); | 
| 1811   RecordStatementPosition(node); | 1448   RecordStatementPosition(node); | 
| 1812   Load(node->expression()); | 1449   Load(node->expression()); | 
| 1813 | 1450 | 
| 1814   // Move the function result into eax | 1451   // Move the function result into eax | 
| 1815   __ pop(eax); | 1452   __ pop(eax); | 
| 1816 | 1453 | 
| 1817   // If we're inside a try statement or the return instruction | 1454   // If we're inside a try statement or the return instruction | 
| 1818   // sequence has been generated, we just jump to that | 1455   // sequence has been generated, we just jump to that | 
| 1819   // point. Otherwise, we generate the return instruction sequence and | 1456   // point. Otherwise, we generate the return instruction sequence and | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 1837     __ ret((scope_->num_parameters() + 1) * kPointerSize); | 1474     __ ret((scope_->num_parameters() + 1) * kPointerSize); | 
| 1838 | 1475 | 
| 1839     // Check that the size of the code used for returning matches what is | 1476     // Check that the size of the code used for returning matches what is | 
| 1840     // expected by the debugger. | 1477     // expected by the debugger. | 
| 1841     ASSERT_EQ(Debug::kIa32JSReturnSequenceLength, | 1478     ASSERT_EQ(Debug::kIa32JSReturnSequenceLength, | 
| 1842               __ SizeOfCodeGeneratedSince(&check_exit_codesize)); | 1479               __ SizeOfCodeGeneratedSince(&check_exit_codesize)); | 
| 1843   } | 1480   } | 
| 1844 } | 1481 } | 
| 1845 | 1482 | 
| 1846 | 1483 | 
| 1847 void Ia32CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { | 1484 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { | 
| 1848   Comment cmnt(masm_, "[ WithEnterStatement"); | 1485   Comment cmnt(masm_, "[ WithEnterStatement"); | 
| 1849   RecordStatementPosition(node); | 1486   RecordStatementPosition(node); | 
| 1850   Load(node->expression()); | 1487   Load(node->expression()); | 
| 1851   __ CallRuntime(Runtime::kPushContext, 1); | 1488   __ CallRuntime(Runtime::kPushContext, 1); | 
| 1852 | 1489 | 
| 1853   if (kDebug) { | 1490   if (kDebug) { | 
| 1854     Label verified_true; | 1491     Label verified_true; | 
| 1855     // Verify eax and esi are the same in debug mode | 1492     // Verify eax and esi are the same in debug mode | 
| 1856     __ cmp(eax, Operand(esi)); | 1493     __ cmp(eax, Operand(esi)); | 
| 1857     __ j(equal, &verified_true); | 1494     __ j(equal, &verified_true); | 
| 1858     __ int3(); | 1495     __ int3(); | 
| 1859     __ bind(&verified_true); | 1496     __ bind(&verified_true); | 
| 1860   } | 1497   } | 
| 1861 | 1498 | 
| 1862   // Update context local. | 1499   // Update context local. | 
| 1863   __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); | 1500   __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); | 
| 1864 } | 1501 } | 
| 1865 | 1502 | 
| 1866 | 1503 | 
| 1867 void Ia32CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { | 1504 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { | 
| 1868   Comment cmnt(masm_, "[ WithExitStatement"); | 1505   Comment cmnt(masm_, "[ WithExitStatement"); | 
| 1869   // Pop context. | 1506   // Pop context. | 
| 1870   __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX)); | 1507   __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX)); | 
| 1871   // Update context local. | 1508   // Update context local. | 
| 1872   __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); | 1509   __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); | 
| 1873 } | 1510 } | 
| 1874 | 1511 | 
| 1875 int Ia32CodeGenerator::FastCaseSwitchMaxOverheadFactor() { | 1512 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { | 
| 1876     return kFastSwitchMaxOverheadFactor; | 1513     return kFastSwitchMaxOverheadFactor; | 
| 1877 } | 1514 } | 
| 1878 | 1515 | 
| 1879 int Ia32CodeGenerator::FastCaseSwitchMinCaseCount() { | 1516 int CodeGenerator::FastCaseSwitchMinCaseCount() { | 
| 1880     return kFastSwitchMinCaseCount; | 1517     return kFastSwitchMinCaseCount; | 
| 1881 } | 1518 } | 
| 1882 | 1519 | 
| 1883 // Generate a computed jump to a switch case. | 1520 // Generate a computed jump to a switch case. | 
| 1884 void Ia32CodeGenerator::GenerateFastCaseSwitchJumpTable( | 1521 void CodeGenerator::GenerateFastCaseSwitchJumpTable( | 
| 1885     SwitchStatement* node, int min_index, int range, Label *fail_label, | 1522     SwitchStatement* node, int min_index, int range, Label *fail_label, | 
| 1886     SmartPointer<Label*> &case_targets, SmartPointer<Label> &case_labels) { | 1523     SmartPointer<Label*> &case_targets, SmartPointer<Label> &case_labels) { | 
| 1887   // Notice: Internal references, used by both the jmp instruction and | 1524   // Notice: Internal references, used by both the jmp instruction and | 
| 1888   // the table entries, need to be relocated if the buffer grows. This | 1525   // the table entries, need to be relocated if the buffer grows. This | 
| 1889   // prevents the forward use of Labels, since a displacement cannot | 1526   // prevents the forward use of Labels, since a displacement cannot | 
| 1890   // survive relocation, and it also cannot safely be distinguished | 1527   // survive relocation, and it also cannot safely be distinguished | 
| 1891   // from a real address.  Instead we put in zero-values as | 1528   // from a real address.  Instead we put in zero-values as | 
| 1892   // placeholders, and fill in the addresses after the labels have been | 1529   // placeholders, and fill in the addresses after the labels have been | 
| 1893   // bound. | 1530   // bound. | 
| 1894 | 1531 | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
| 1920 | 1557 | 
| 1921   GenerateFastCaseSwitchCases(node, case_labels); | 1558   GenerateFastCaseSwitchCases(node, case_labels); | 
| 1922 | 1559 | 
| 1923   for (int i = 0, entry_pos = table_start.pos(); | 1560   for (int i = 0, entry_pos = table_start.pos(); | 
| 1924        i < range; i++, entry_pos += sizeof(uint32_t)) { | 1561        i < range; i++, entry_pos += sizeof(uint32_t)) { | 
| 1925     __ WriteInternalReference(entry_pos, *case_targets[i]); | 1562     __ WriteInternalReference(entry_pos, *case_targets[i]); | 
| 1926   } | 1563   } | 
| 1927 } | 1564 } | 
| 1928 | 1565 | 
| 1929 | 1566 | 
| 1930 void Ia32CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { | 1567 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { | 
| 1931   Comment cmnt(masm_, "[ SwitchStatement"); | 1568   Comment cmnt(masm_, "[ SwitchStatement"); | 
| 1932   RecordStatementPosition(node); | 1569   RecordStatementPosition(node); | 
| 1933   node->set_break_stack_height(break_stack_height_); | 1570   node->set_break_stack_height(break_stack_height_); | 
| 1934 | 1571 | 
| 1935   Load(node->tag()); | 1572   Load(node->tag()); | 
| 1936 | 1573 | 
| 1937   if (TryGenerateFastCaseSwitchStatement(node)) { | 1574   if (TryGenerateFastCaseSwitchStatement(node)) { | 
| 1938     return; | 1575     return; | 
| 1939   } | 1576   } | 
| 1940 | 1577 | 
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1987   } else { | 1624   } else { | 
| 1988     // Remove the switch value from the stack. | 1625     // Remove the switch value from the stack. | 
| 1989     __ pop(eax); | 1626     __ pop(eax); | 
| 1990   } | 1627   } | 
| 1991 | 1628 | 
| 1992   __ bind(&fall_through); | 1629   __ bind(&fall_through); | 
| 1993   __ bind(node->break_target()); | 1630   __ bind(node->break_target()); | 
| 1994 } | 1631 } | 
| 1995 | 1632 | 
| 1996 | 1633 | 
| 1997 void Ia32CodeGenerator::VisitLoopStatement(LoopStatement* node) { | 1634 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { | 
| 1998   Comment cmnt(masm_, "[ LoopStatement"); | 1635   Comment cmnt(masm_, "[ LoopStatement"); | 
| 1999   RecordStatementPosition(node); | 1636   RecordStatementPosition(node); | 
| 2000   node->set_break_stack_height(break_stack_height_); | 1637   node->set_break_stack_height(break_stack_height_); | 
| 2001 | 1638 | 
| 2002   // simple condition analysis | 1639   // simple condition analysis | 
| 2003   enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; | 1640   enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; | 
| 2004   if (node->cond() == NULL) { | 1641   if (node->cond() == NULL) { | 
| 2005     ASSERT(node->type() == LoopStatement::FOR_LOOP); | 1642     ASSERT(node->type() == LoopStatement::FOR_LOOP); | 
| 2006     info = ALWAYS_TRUE; | 1643     info = ALWAYS_TRUE; | 
| 2007   } else { | 1644   } else { | 
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2056                     node->break_target(), true); | 1693                     node->break_target(), true); | 
| 2057       Branch(true, &loop); | 1694       Branch(true, &loop); | 
| 2058       break; | 1695       break; | 
| 2059   } | 1696   } | 
| 2060 | 1697 | 
| 2061   // exit | 1698   // exit | 
| 2062   __ bind(node->break_target()); | 1699   __ bind(node->break_target()); | 
| 2063 } | 1700 } | 
| 2064 | 1701 | 
| 2065 | 1702 | 
| 2066 void Ia32CodeGenerator::VisitForInStatement(ForInStatement* node) { | 1703 void CodeGenerator::VisitForInStatement(ForInStatement* node) { | 
| 2067   Comment cmnt(masm_, "[ ForInStatement"); | 1704   Comment cmnt(masm_, "[ ForInStatement"); | 
| 2068   RecordStatementPosition(node); | 1705   RecordStatementPosition(node); | 
| 2069 | 1706 | 
| 2070   // We keep stuff on the stack while the body is executing. | 1707   // We keep stuff on the stack while the body is executing. | 
| 2071   // Record it, so that a break/continue crossing this statement | 1708   // Record it, so that a break/continue crossing this statement | 
| 2072   // can restore the stack. | 1709   // can restore the stack. | 
| 2073   const int kForInStackSize = 5 * kPointerSize; | 1710   const int kForInStackSize = 5 * kPointerSize; | 
| 2074   break_stack_height_ += kForInStackSize; | 1711   break_stack_height_ += kForInStackSize; | 
| 2075   node->set_break_stack_height(break_stack_height_); | 1712   node->set_break_stack_height(break_stack_height_); | 
| 2076 | 1713 | 
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2244   __ bind(node->break_target()); | 1881   __ bind(node->break_target()); | 
| 2245   __ add(Operand(esp), Immediate(5 * kPointerSize)); | 1882   __ add(Operand(esp), Immediate(5 * kPointerSize)); | 
| 2246 | 1883 | 
| 2247   // Exit. | 1884   // Exit. | 
| 2248   __ bind(&exit); | 1885   __ bind(&exit); | 
| 2249 | 1886 | 
| 2250   break_stack_height_ -= kForInStackSize; | 1887   break_stack_height_ -= kForInStackSize; | 
| 2251 } | 1888 } | 
| 2252 | 1889 | 
| 2253 | 1890 | 
| 2254 void Ia32CodeGenerator::VisitTryCatch(TryCatch* node) { | 1891 void CodeGenerator::VisitTryCatch(TryCatch* node) { | 
| 2255   Comment cmnt(masm_, "[ TryCatch"); | 1892   Comment cmnt(masm_, "[ TryCatch"); | 
| 2256 | 1893 | 
| 2257   Label try_block, exit; | 1894   Label try_block, exit; | 
| 2258 | 1895 | 
| 2259   __ call(&try_block); | 1896   __ call(&try_block); | 
| 2260   // --- Catch block --- | 1897   // --- Catch block --- | 
| 2261   __ push(eax); | 1898   __ push(eax); | 
| 2262 | 1899 | 
| 2263   // Store the caught exception in the catch variable. | 1900   // Store the caught exception in the catch variable. | 
| 2264   { Reference ref(this, node->catch_var()); | 1901   { Reference ref(this, node->catch_var()); | 
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2343              Immediate(StackHandlerConstants::kSize - kPointerSize)); | 1980              Immediate(StackHandlerConstants::kSize - kPointerSize)); | 
| 2344       // next_sp popped. | 1981       // next_sp popped. | 
| 2345       __ jmp(shadows[i]->shadowed()); | 1982       __ jmp(shadows[i]->shadowed()); | 
| 2346     } | 1983     } | 
| 2347   } | 1984   } | 
| 2348 | 1985 | 
| 2349   __ bind(&exit); | 1986   __ bind(&exit); | 
| 2350 } | 1987 } | 
| 2351 | 1988 | 
| 2352 | 1989 | 
| 2353 void Ia32CodeGenerator::VisitTryFinally(TryFinally* node) { | 1990 void CodeGenerator::VisitTryFinally(TryFinally* node) { | 
| 2354   Comment cmnt(masm_, "[ TryFinally"); | 1991   Comment cmnt(masm_, "[ TryFinally"); | 
| 2355 | 1992 | 
| 2356   // State: Used to keep track of reason for entering the finally | 1993   // State: Used to keep track of reason for entering the finally | 
| 2357   // block. Should probably be extended to hold information for | 1994   // block. Should probably be extended to hold information for | 
| 2358   // break/continue from within the try block. | 1995   // break/continue from within the try block. | 
| 2359   enum { FALLING, THROWING, JUMPING }; | 1996   enum { FALLING, THROWING, JUMPING }; | 
| 2360 | 1997 | 
| 2361   Label exit, unlink, try_block, finally_block; | 1998   Label exit, unlink, try_block, finally_block; | 
| 2362 | 1999 | 
| 2363   __ call(&try_block); | 2000   __ call(&try_block); | 
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2472 | 2109 | 
| 2473   // Rethrow exception. | 2110   // Rethrow exception. | 
| 2474   __ push(eax);  // undo pop from above | 2111   __ push(eax);  // undo pop from above | 
| 2475   __ CallRuntime(Runtime::kReThrow, 1); | 2112   __ CallRuntime(Runtime::kReThrow, 1); | 
| 2476 | 2113 | 
| 2477   // Done. | 2114   // Done. | 
| 2478   __ bind(&exit); | 2115   __ bind(&exit); | 
| 2479 } | 2116 } | 
| 2480 | 2117 | 
| 2481 | 2118 | 
| 2482 void Ia32CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { | 2119 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { | 
| 2483   Comment cmnt(masm_, "[ DebuggerStatement"); | 2120   Comment cmnt(masm_, "[ DebuggerStatement"); | 
| 2484   RecordStatementPosition(node); | 2121   RecordStatementPosition(node); | 
| 2485   __ CallRuntime(Runtime::kDebugBreak, 1); | 2122   __ CallRuntime(Runtime::kDebugBreak, 1); | 
| 2486   __ push(eax); | 2123   __ push(eax); | 
| 2487 } | 2124 } | 
| 2488 | 2125 | 
| 2489 | 2126 | 
| 2490 void Ia32CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { | 2127 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { | 
| 2491   ASSERT(boilerplate->IsBoilerplate()); | 2128   ASSERT(boilerplate->IsBoilerplate()); | 
| 2492 | 2129 | 
| 2493   // Push the boilerplate on the stack. | 2130   // Push the boilerplate on the stack. | 
| 2494   __ push(Immediate(boilerplate)); | 2131   __ push(Immediate(boilerplate)); | 
| 2495 | 2132 | 
| 2496   // Create a new closure. | 2133   // Create a new closure. | 
| 2497   __ push(esi); | 2134   __ push(esi); | 
| 2498   __ CallRuntime(Runtime::kNewClosure, 2); | 2135   __ CallRuntime(Runtime::kNewClosure, 2); | 
| 2499   __ push(eax); | 2136   __ push(eax); | 
| 2500 } | 2137 } | 
| 2501 | 2138 | 
| 2502 | 2139 | 
| 2503 void Ia32CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { | 2140 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { | 
| 2504   Comment cmnt(masm_, "[ FunctionLiteral"); | 2141   Comment cmnt(masm_, "[ FunctionLiteral"); | 
| 2505 | 2142 | 
| 2506   // Build the function boilerplate and instantiate it. | 2143   // Build the function boilerplate and instantiate it. | 
| 2507   Handle<JSFunction> boilerplate = BuildBoilerplate(node); | 2144   Handle<JSFunction> boilerplate = BuildBoilerplate(node); | 
| 2508   // Check for stack-overflow exception. | 2145   // Check for stack-overflow exception. | 
| 2509   if (HasStackOverflow()) return; | 2146   if (HasStackOverflow()) return; | 
| 2510   InstantiateBoilerplate(boilerplate); | 2147   InstantiateBoilerplate(boilerplate); | 
| 2511 } | 2148 } | 
| 2512 | 2149 | 
| 2513 | 2150 | 
| 2514 void Ia32CodeGenerator::VisitFunctionBoilerplateLiteral( | 2151 void CodeGenerator::VisitFunctionBoilerplateLiteral( | 
| 2515     FunctionBoilerplateLiteral* node) { | 2152     FunctionBoilerplateLiteral* node) { | 
| 2516   Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); | 2153   Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); | 
| 2517   InstantiateBoilerplate(node->boilerplate()); | 2154   InstantiateBoilerplate(node->boilerplate()); | 
| 2518 } | 2155 } | 
| 2519 | 2156 | 
| 2520 | 2157 | 
| 2521 void Ia32CodeGenerator::VisitConditional(Conditional* node) { | 2158 void CodeGenerator::VisitConditional(Conditional* node) { | 
| 2522   Comment cmnt(masm_, "[ Conditional"); | 2159   Comment cmnt(masm_, "[ Conditional"); | 
| 2523   Label then, else_, exit; | 2160   Label then, else_, exit; | 
| 2524   LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); | 2161   LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); | 
| 2525   Branch(false, &else_); | 2162   Branch(false, &else_); | 
| 2526   __ bind(&then); | 2163   __ bind(&then); | 
| 2527   Load(node->then_expression(), typeof_state()); | 2164   Load(node->then_expression(), typeof_state()); | 
| 2528   __ jmp(&exit); | 2165   __ jmp(&exit); | 
| 2529   __ bind(&else_); | 2166   __ bind(&else_); | 
| 2530   Load(node->else_expression(), typeof_state()); | 2167   Load(node->else_expression(), typeof_state()); | 
| 2531   __ bind(&exit); | 2168   __ bind(&exit); | 
| 2532 } | 2169 } | 
| 2533 | 2170 | 
| 2534 | 2171 | 
| 2535 void Ia32CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { | 2172 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { | 
| 2536   if (slot->type() == Slot::LOOKUP) { | 2173   if (slot->type() == Slot::LOOKUP) { | 
| 2537     ASSERT(slot->var()->mode() == Variable::DYNAMIC); | 2174     ASSERT(slot->var()->mode() == Variable::DYNAMIC); | 
| 2538 | 2175 | 
| 2539     // For now, just do a runtime call. | 2176     // For now, just do a runtime call. | 
| 2540     __ push(esi); | 2177     __ push(esi); | 
| 2541     __ push(Immediate(slot->var()->name())); | 2178     __ push(Immediate(slot->var()->name())); | 
| 2542 | 2179 | 
| 2543     if (typeof_state == INSIDE_TYPEOF) { | 2180     if (typeof_state == INSIDE_TYPEOF) { | 
| 2544       __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 2181       __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 
| 2545     } else { | 2182     } else { | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 2563       __ mov(eax, Factory::undefined_value()); | 2200       __ mov(eax, Factory::undefined_value()); | 
| 2564       __ bind(&exit); | 2201       __ bind(&exit); | 
| 2565       __ push(eax); | 2202       __ push(eax); | 
| 2566     } else { | 2203     } else { | 
| 2567       __ push(SlotOperand(slot, ecx)); | 2204       __ push(SlotOperand(slot, ecx)); | 
| 2568     } | 2205     } | 
| 2569   } | 2206   } | 
| 2570 } | 2207 } | 
| 2571 | 2208 | 
| 2572 | 2209 | 
| 2573 void Ia32CodeGenerator::VisitSlot(Slot* node) { | 2210 void CodeGenerator::VisitSlot(Slot* node) { | 
| 2574   Comment cmnt(masm_, "[ Slot"); | 2211   Comment cmnt(masm_, "[ Slot"); | 
| 2575   LoadFromSlot(node, typeof_state()); | 2212   LoadFromSlot(node, typeof_state()); | 
| 2576 } | 2213 } | 
| 2577 | 2214 | 
| 2578 | 2215 | 
| 2579 void Ia32CodeGenerator::VisitVariableProxy(VariableProxy* node) { | 2216 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { | 
| 2580   Comment cmnt(masm_, "[ VariableProxy"); | 2217   Comment cmnt(masm_, "[ VariableProxy"); | 
| 2581   Variable* var = node->var(); | 2218   Variable* var = node->var(); | 
| 2582   Expression* expr = var->rewrite(); | 2219   Expression* expr = var->rewrite(); | 
| 2583   if (expr != NULL) { | 2220   if (expr != NULL) { | 
| 2584     Visit(expr); | 2221     Visit(expr); | 
| 2585   } else { | 2222   } else { | 
| 2586     ASSERT(var->is_global()); | 2223     ASSERT(var->is_global()); | 
| 2587     Reference ref(this, node); | 2224     Reference ref(this, node); | 
| 2588     ref.GetValue(typeof_state()); | 2225     ref.GetValue(typeof_state()); | 
| 2589   } | 2226   } | 
| 2590 } | 2227 } | 
| 2591 | 2228 | 
| 2592 | 2229 | 
| 2593 void Ia32CodeGenerator::VisitLiteral(Literal* node) { | 2230 void CodeGenerator::VisitLiteral(Literal* node) { | 
| 2594   Comment cmnt(masm_, "[ Literal"); | 2231   Comment cmnt(masm_, "[ Literal"); | 
| 2595   if (node->handle()->IsSmi() && !IsInlineSmi(node)) { | 2232   if (node->handle()->IsSmi() && !IsInlineSmi(node)) { | 
| 2596     // To prevent long attacker-controlled byte sequences in code, larger | 2233     // To prevent long attacker-controlled byte sequences in code, larger | 
| 2597     // Smis are loaded in two steps. | 2234     // Smis are loaded in two steps. | 
| 2598     int bits = reinterpret_cast<int>(*node->handle()); | 2235     int bits = reinterpret_cast<int>(*node->handle()); | 
| 2599     __ mov(eax, bits & 0x0000FFFF); | 2236     __ mov(eax, bits & 0x0000FFFF); | 
| 2600     __ xor_(eax, bits & 0xFFFF0000); | 2237     __ xor_(eax, bits & 0xFFFF0000); | 
| 2601     __ push(eax); | 2238     __ push(eax); | 
| 2602   } else { | 2239   } else { | 
| 2603     __ push(Immediate(node->handle())); | 2240     __ push(Immediate(node->handle())); | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 2627   __ push(Immediate(Smi::FromInt(node_->literal_index()))); | 2264   __ push(Immediate(Smi::FromInt(node_->literal_index()))); | 
| 2628   // RegExp pattern (2). | 2265   // RegExp pattern (2). | 
| 2629   __ push(Immediate(node_->pattern())); | 2266   __ push(Immediate(node_->pattern())); | 
| 2630   // RegExp flags (3). | 2267   // RegExp flags (3). | 
| 2631   __ push(Immediate(node_->flags())); | 2268   __ push(Immediate(node_->flags())); | 
| 2632   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 2269   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 
| 2633   __ mov(ebx, Operand(eax));  // "caller" expects result in ebx | 2270   __ mov(ebx, Operand(eax));  // "caller" expects result in ebx | 
| 2634 } | 2271 } | 
| 2635 | 2272 | 
| 2636 | 2273 | 
| 2637 void Ia32CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { | 2274 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { | 
| 2638   Comment cmnt(masm_, "[ RegExp Literal"); | 2275   Comment cmnt(masm_, "[ RegExp Literal"); | 
| 2639   RegExpDeferred* deferred = new RegExpDeferred(this, node); | 2276   RegExpDeferred* deferred = new RegExpDeferred(this, node); | 
| 2640 | 2277 | 
| 2641   // Retrieve the literal array and check the allocated entry. | 2278   // Retrieve the literal array and check the allocated entry. | 
| 2642 | 2279 | 
| 2643   // Load the function of this activation. | 2280   // Load the function of this activation. | 
| 2644   __ mov(ecx, FunctionOperand()); | 2281   __ mov(ecx, FunctionOperand()); | 
| 2645 | 2282 | 
| 2646   // Load the literals array of the function. | 2283   // Load the literals array of the function. | 
| 2647   __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); | 2284   __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2687   __ push(Operand(ecx)); | 2324   __ push(Operand(ecx)); | 
| 2688   // Literal index (1). | 2325   // Literal index (1). | 
| 2689   __ push(Immediate(Smi::FromInt(node_->literal_index()))); | 2326   __ push(Immediate(Smi::FromInt(node_->literal_index()))); | 
| 2690   // Constant properties (2). | 2327   // Constant properties (2). | 
| 2691   __ push(Immediate(node_->constant_properties())); | 2328   __ push(Immediate(node_->constant_properties())); | 
| 2692   __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); | 2329   __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); | 
| 2693   __ mov(ebx, Operand(eax)); | 2330   __ mov(ebx, Operand(eax)); | 
| 2694 } | 2331 } | 
| 2695 | 2332 | 
| 2696 | 2333 | 
| 2697 void Ia32CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { | 2334 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { | 
| 2698   Comment cmnt(masm_, "[ ObjectLiteral"); | 2335   Comment cmnt(masm_, "[ ObjectLiteral"); | 
| 2699   ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); | 2336   ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); | 
| 2700 | 2337 | 
| 2701   // Retrieve the literal array and check the allocated entry. | 2338   // Retrieve the literal array and check the allocated entry. | 
| 2702 | 2339 | 
| 2703   // Load the function of this activation. | 2340   // Load the function of this activation. | 
| 2704   __ mov(ecx, FunctionOperand()); | 2341   __ mov(ecx, FunctionOperand()); | 
| 2705 | 2342 | 
| 2706   // Load the literals array of the function. | 2343   // Load the literals array of the function. | 
| 2707   __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); | 2344   __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); | 
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2777         __ CallRuntime(Runtime::kDefineAccessor, 4); | 2414         __ CallRuntime(Runtime::kDefineAccessor, 4); | 
| 2778         // Ignore result. | 2415         // Ignore result. | 
| 2779         break; | 2416         break; | 
| 2780       } | 2417       } | 
| 2781       default: UNREACHABLE(); | 2418       default: UNREACHABLE(); | 
| 2782     } | 2419     } | 
| 2783   } | 2420   } | 
| 2784 } | 2421 } | 
| 2785 | 2422 | 
| 2786 | 2423 | 
| 2787 void Ia32CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { | 2424 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { | 
| 2788   Comment cmnt(masm_, "[ ArrayLiteral"); | 2425   Comment cmnt(masm_, "[ ArrayLiteral"); | 
| 2789 | 2426 | 
| 2790   // Call runtime to create the array literal. | 2427   // Call runtime to create the array literal. | 
| 2791   __ push(Immediate(node->literals())); | 2428   __ push(Immediate(node->literals())); | 
| 2792   // Load the function of this frame. | 2429   // Load the function of this frame. | 
| 2793   __ mov(ecx, FunctionOperand()); | 2430   __ mov(ecx, FunctionOperand()); | 
| 2794   // Load the literals array of the function. | 2431   // Load the literals array of the function. | 
| 2795   __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); | 2432   __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); | 
| 2796   __ push(ecx); | 2433   __ push(ecx); | 
| 2797   __ CallRuntime(Runtime::kCreateArrayLiteral, 2); | 2434   __ CallRuntime(Runtime::kCreateArrayLiteral, 2); | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 2821       int offset = i * kPointerSize + Array::kHeaderSize; | 2458       int offset = i * kPointerSize + Array::kHeaderSize; | 
| 2822       __ mov(FieldOperand(ecx, offset), eax); | 2459       __ mov(FieldOperand(ecx, offset), eax); | 
| 2823 | 2460 | 
| 2824       // Update the write barrier for the array address. | 2461       // Update the write barrier for the array address. | 
| 2825       __ RecordWrite(ecx, offset, eax, ebx); | 2462       __ RecordWrite(ecx, offset, eax, ebx); | 
| 2826     } | 2463     } | 
| 2827   } | 2464   } | 
| 2828 } | 2465 } | 
| 2829 | 2466 | 
| 2830 | 2467 | 
| 2831 bool Ia32CodeGenerator::IsInlineSmi(Literal* literal) { | 2468 bool CodeGenerator::IsInlineSmi(Literal* literal) { | 
| 2832   if (literal == NULL || !literal->handle()->IsSmi()) return false; | 2469   if (literal == NULL || !literal->handle()->IsSmi()) return false; | 
| 2833   int int_value = Smi::cast(*literal->handle())->value(); | 2470   int int_value = Smi::cast(*literal->handle())->value(); | 
| 2834   return is_intn(int_value, kMaxSmiInlinedBits); | 2471   return is_intn(int_value, kMaxSmiInlinedBits); | 
| 2835 } | 2472 } | 
| 2836 | 2473 | 
| 2837 | 2474 | 
| 2838 void Ia32CodeGenerator::VisitAssignment(Assignment* node) { | 2475 void CodeGenerator::VisitAssignment(Assignment* node) { | 
| 2839   Comment cmnt(masm_, "[ Assignment"); | 2476   Comment cmnt(masm_, "[ Assignment"); | 
| 2840 | 2477 | 
| 2841   RecordStatementPosition(node); | 2478   RecordStatementPosition(node); | 
| 2842   Reference target(this, node->target()); | 2479   Reference target(this, node->target()); | 
| 2843   if (target.is_illegal()) return; | 2480   if (target.is_illegal()) return; | 
| 2844 | 2481 | 
| 2845   if (node->op() == Token::ASSIGN || | 2482   if (node->op() == Token::ASSIGN || | 
| 2846       node->op() == Token::INIT_VAR || | 2483       node->op() == Token::INIT_VAR || | 
| 2847       node->op() == Token::INIT_CONST) { | 2484       node->op() == Token::INIT_CONST) { | 
| 2848     Load(node->value()); | 2485     Load(node->value()); | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 2870       // and initialize the actual constant declared. Dynamic variable | 2507       // and initialize the actual constant declared. Dynamic variable | 
| 2871       // initializations are simply assignments and use SetValue. | 2508       // initializations are simply assignments and use SetValue. | 
| 2872       target.SetValue(CONST_INIT); | 2509       target.SetValue(CONST_INIT); | 
| 2873     } else { | 2510     } else { | 
| 2874       target.SetValue(NOT_CONST_INIT); | 2511       target.SetValue(NOT_CONST_INIT); | 
| 2875     } | 2512     } | 
| 2876   } | 2513   } | 
| 2877 } | 2514 } | 
| 2878 | 2515 | 
| 2879 | 2516 | 
| 2880 void Ia32CodeGenerator::VisitThrow(Throw* node) { | 2517 void CodeGenerator::VisitThrow(Throw* node) { | 
| 2881   Comment cmnt(masm_, "[ Throw"); | 2518   Comment cmnt(masm_, "[ Throw"); | 
| 2882 | 2519 | 
| 2883   Load(node->exception()); | 2520   Load(node->exception()); | 
| 2884   __ RecordPosition(node->position()); | 2521   __ RecordPosition(node->position()); | 
| 2885   __ CallRuntime(Runtime::kThrow, 1); | 2522   __ CallRuntime(Runtime::kThrow, 1); | 
| 2886   __ push(eax); | 2523   __ push(eax); | 
| 2887 } | 2524 } | 
| 2888 | 2525 | 
| 2889 | 2526 | 
| 2890 void Ia32CodeGenerator::VisitProperty(Property* node) { | 2527 void CodeGenerator::VisitProperty(Property* node) { | 
| 2891   Comment cmnt(masm_, "[ Property"); | 2528   Comment cmnt(masm_, "[ Property"); | 
|  | 2529 | 
| 2892   Reference property(this, node); | 2530   Reference property(this, node); | 
| 2893   property.GetValue(typeof_state()); | 2531   property.GetValue(typeof_state()); | 
| 2894 } | 2532 } | 
| 2895 | 2533 | 
| 2896 | 2534 | 
| 2897 void Ia32CodeGenerator::VisitCall(Call* node) { | 2535 void CodeGenerator::VisitCall(Call* node) { | 
| 2898   Comment cmnt(masm_, "[ Call"); | 2536   Comment cmnt(masm_, "[ Call"); | 
| 2899 | 2537 | 
| 2900   ZoneList<Expression*>* args = node->arguments(); | 2538   ZoneList<Expression*>* args = node->arguments(); | 
| 2901 | 2539 | 
| 2902   RecordStatementPosition(node); | 2540   RecordStatementPosition(node); | 
| 2903 | 2541 | 
| 2904   // Check if the function is a variable or a property. | 2542   // Check if the function is a variable or a property. | 
| 2905   Expression* function = node->expression(); | 2543   Expression* function = node->expression(); | 
| 2906   Variable* var = function->AsVariableProxy()->AsVariable(); | 2544   Variable* var = function->AsVariableProxy()->AsVariable(); | 
| 2907   Property* property = function->AsProperty(); | 2545   Property* property = function->AsProperty(); | 
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3009 | 2647 | 
| 3010     // Pass the global object as the receiver. | 2648     // Pass the global object as the receiver. | 
| 3011     LoadGlobal(); | 2649     LoadGlobal(); | 
| 3012 | 2650 | 
| 3013     // Call the function. | 2651     // Call the function. | 
| 3014     CallWithArguments(args, node->position()); | 2652     CallWithArguments(args, node->position()); | 
| 3015   } | 2653   } | 
| 3016 } | 2654 } | 
| 3017 | 2655 | 
| 3018 | 2656 | 
| 3019 void Ia32CodeGenerator::VisitCallNew(CallNew* node) { | 2657 void CodeGenerator::VisitCallNew(CallNew* node) { | 
| 3020   Comment cmnt(masm_, "[ CallNew"); | 2658   Comment cmnt(masm_, "[ CallNew"); | 
| 3021 | 2659 | 
| 3022   // According to ECMA-262, section 11.2.2, page 44, the function | 2660   // According to ECMA-262, section 11.2.2, page 44, the function | 
| 3023   // expression in new calls must be evaluated before the | 2661   // expression in new calls must be evaluated before the | 
| 3024   // arguments. This is different from ordinary calls, where the | 2662   // arguments. This is different from ordinary calls, where the | 
| 3025   // actual function to call is resolved after the arguments have been | 2663   // actual function to call is resolved after the arguments have been | 
| 3026   // evaluated. | 2664   // evaluated. | 
| 3027 | 2665 | 
| 3028   // Compute function to call and use the global object as the | 2666   // Compute function to call and use the global object as the | 
| 3029   // receiver. | 2667   // receiver. | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 3045 | 2683 | 
| 3046   // Call the construct call builtin that handles allocation and | 2684   // Call the construct call builtin that handles allocation and | 
| 3047   // constructor invocation. | 2685   // constructor invocation. | 
| 3048   __ RecordPosition(node->position()); | 2686   __ RecordPosition(node->position()); | 
| 3049   __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), | 2687   __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), | 
| 3050           RelocInfo::CONSTRUCT_CALL); | 2688           RelocInfo::CONSTRUCT_CALL); | 
| 3051   __ mov(TOS, eax);  // discard the function and "push" the newly created object | 2689   __ mov(TOS, eax);  // discard the function and "push" the newly created object | 
| 3052 } | 2690 } | 
| 3053 | 2691 | 
| 3054 | 2692 | 
| 3055 void Ia32CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { | 2693 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { | 
| 3056   ASSERT(args->length() == 1); | 2694   ASSERT(args->length() == 1); | 
| 3057   Load(args->at(0)); | 2695   Load(args->at(0)); | 
| 3058   __ pop(eax); | 2696   __ pop(eax); | 
| 3059   __ test(eax, Immediate(kSmiTagMask)); | 2697   __ test(eax, Immediate(kSmiTagMask)); | 
| 3060   cc_reg_ = zero; | 2698   cc_reg_ = zero; | 
| 3061 } | 2699 } | 
| 3062 | 2700 | 
| 3063 | 2701 | 
| 3064 void Ia32CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { | 2702 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { | 
| 3065   ASSERT(args->length() == 1); | 2703   ASSERT(args->length() == 1); | 
| 3066   Load(args->at(0)); | 2704   Load(args->at(0)); | 
| 3067   __ pop(eax); | 2705   __ pop(eax); | 
| 3068   __ test(eax, Immediate(kSmiTagMask | 0x80000000)); | 2706   __ test(eax, Immediate(kSmiTagMask | 0x80000000)); | 
| 3069   cc_reg_ = zero; | 2707   cc_reg_ = zero; | 
| 3070 } | 2708 } | 
| 3071 | 2709 | 
| 3072 | 2710 | 
| 3073 // This generates code that performs a charCodeAt() call or returns | 2711 // This generates code that performs a charCodeAt() call or returns | 
| 3074 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. | 2712 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. | 
| 3075 // It can handle flat and sliced strings, 8 and 16 bit characters and | 2713 // It can handle flat and sliced strings, 8 and 16 bit characters and | 
| 3076 // cons strings where the answer is found in the left hand branch of the | 2714 // cons strings where the answer is found in the left hand branch of the | 
| 3077 // cons.  The slow case will flatten the string, which will ensure that | 2715 // cons.  The slow case will flatten the string, which will ensure that | 
| 3078 // the answer is in the left hand side the next time around. | 2716 // the answer is in the left hand side the next time around. | 
| 3079 void Ia32CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { | 2717 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { | 
| 3080   ASSERT(args->length() == 2); | 2718   ASSERT(args->length() == 2); | 
| 3081 | 2719 | 
| 3082   Label slow_case; | 2720   Label slow_case; | 
| 3083   Label end; | 2721   Label end; | 
| 3084   Label not_a_flat_string; | 2722   Label not_a_flat_string; | 
| 3085   Label not_a_cons_string_either; | 2723   Label not_a_cons_string_either; | 
| 3086   Label try_again_with_new_string; | 2724   Label try_again_with_new_string; | 
| 3087   Label ascii_string; | 2725   Label ascii_string; | 
| 3088   Label got_char_code; | 2726   Label got_char_code; | 
| 3089 | 2727 | 
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3195   __ mov(eax, FieldOperand(eax, SlicedString::kBufferOffset)); | 2833   __ mov(eax, FieldOperand(eax, SlicedString::kBufferOffset)); | 
| 3196   __ jmp(&try_again_with_new_string); | 2834   __ jmp(&try_again_with_new_string); | 
| 3197 | 2835 | 
| 3198   __ bind(&slow_case); | 2836   __ bind(&slow_case); | 
| 3199   __ push(Immediate(Factory::undefined_value())); | 2837   __ push(Immediate(Factory::undefined_value())); | 
| 3200 | 2838 | 
| 3201   __ bind(&end); | 2839   __ bind(&end); | 
| 3202 } | 2840 } | 
| 3203 | 2841 | 
| 3204 | 2842 | 
| 3205 void Ia32CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { | 2843 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { | 
| 3206   ASSERT(args->length() == 1); | 2844   ASSERT(args->length() == 1); | 
| 3207   Load(args->at(0)); | 2845   Load(args->at(0)); | 
| 3208   Label answer; | 2846   Label answer; | 
| 3209   // We need the CC bits to come out as not_equal in the case where the | 2847   // We need the CC bits to come out as not_equal in the case where the | 
| 3210   // object is a smi.  This can't be done with the usual test opcode so | 2848   // object is a smi.  This can't be done with the usual test opcode so | 
| 3211   // we copy the object to ecx and do some destructive ops on it that | 2849   // we copy the object to ecx and do some destructive ops on it that | 
| 3212   // result in the right CC bits. | 2850   // result in the right CC bits. | 
| 3213   __ pop(eax); | 2851   __ pop(eax); | 
| 3214   __ mov(ecx, Operand(eax)); | 2852   __ mov(ecx, Operand(eax)); | 
| 3215   __ and_(ecx, kSmiTagMask); | 2853   __ and_(ecx, kSmiTagMask); | 
| 3216   __ xor_(ecx, kSmiTagMask); | 2854   __ xor_(ecx, kSmiTagMask); | 
| 3217   __ j(not_equal, &answer, not_taken); | 2855   __ j(not_equal, &answer, not_taken); | 
| 3218   // It is a heap object - get map. | 2856   // It is a heap object - get map. | 
| 3219   __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); | 2857   __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); | 
| 3220   __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset)); | 2858   __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset)); | 
| 3221   // Check if the object is a JS array or not. | 2859   // Check if the object is a JS array or not. | 
| 3222   __ cmp(eax, JS_ARRAY_TYPE); | 2860   __ cmp(eax, JS_ARRAY_TYPE); | 
| 3223   __ bind(&answer); | 2861   __ bind(&answer); | 
| 3224   cc_reg_ = equal; | 2862   cc_reg_ = equal; | 
| 3225 } | 2863 } | 
| 3226 | 2864 | 
| 3227 | 2865 | 
| 3228 void Ia32CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { | 2866 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { | 
| 3229   ASSERT(args->length() == 0); | 2867   ASSERT(args->length() == 0); | 
| 3230 | 2868 | 
| 3231   // Seed the result with the formal parameters count, which will be | 2869   // Seed the result with the formal parameters count, which will be | 
| 3232   // used in case no arguments adaptor frame is found below the | 2870   // used in case no arguments adaptor frame is found below the | 
| 3233   // current frame. | 2871   // current frame. | 
| 3234   __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); | 2872   __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); | 
| 3235 | 2873 | 
| 3236   // Call the shared stub to get to the arguments.length. | 2874   // Call the shared stub to get to the arguments.length. | 
| 3237   ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); | 2875   ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); | 
| 3238   __ CallStub(&stub); | 2876   __ CallStub(&stub); | 
| 3239   __ push(eax); | 2877   __ push(eax); | 
| 3240 } | 2878 } | 
| 3241 | 2879 | 
| 3242 | 2880 | 
| 3243 void Ia32CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { | 2881 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { | 
| 3244   ASSERT(args->length() == 1); | 2882   ASSERT(args->length() == 1); | 
| 3245   Label leave; | 2883   Label leave; | 
| 3246   Load(args->at(0));  // Load the object. | 2884   Load(args->at(0));  // Load the object. | 
| 3247   __ mov(eax, TOS); | 2885   __ mov(eax, TOS); | 
| 3248   // if (object->IsSmi()) return object. | 2886   // if (object->IsSmi()) return object. | 
| 3249   __ test(eax, Immediate(kSmiTagMask)); | 2887   __ test(eax, Immediate(kSmiTagMask)); | 
| 3250   __ j(zero, &leave, taken); | 2888   __ j(zero, &leave, taken); | 
| 3251   // It is a heap object - get map. | 2889   // It is a heap object - get map. | 
| 3252   __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | 2890   __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | 
| 3253   __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 2891   __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 
| 3254   // if (!object->IsJSValue()) return object. | 2892   // if (!object->IsJSValue()) return object. | 
| 3255   __ cmp(ecx, JS_VALUE_TYPE); | 2893   __ cmp(ecx, JS_VALUE_TYPE); | 
| 3256   __ j(not_equal, &leave, not_taken); | 2894   __ j(not_equal, &leave, not_taken); | 
| 3257   __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); | 2895   __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); | 
| 3258   __ mov(TOS, eax); | 2896   __ mov(TOS, eax); | 
| 3259   __ bind(&leave); | 2897   __ bind(&leave); | 
| 3260 } | 2898 } | 
| 3261 | 2899 | 
| 3262 | 2900 | 
| 3263 void Ia32CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { | 2901 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { | 
| 3264   ASSERT(args->length() == 2); | 2902   ASSERT(args->length() == 2); | 
| 3265   Label leave; | 2903   Label leave; | 
| 3266   Load(args->at(0));  // Load the object. | 2904   Load(args->at(0));  // Load the object. | 
| 3267   Load(args->at(1));  // Load the value. | 2905   Load(args->at(1));  // Load the value. | 
| 3268   __ mov(eax, (Operand(esp, kPointerSize))); | 2906   __ mov(eax, (Operand(esp, kPointerSize))); | 
| 3269   __ mov(ecx, TOS); | 2907   __ mov(ecx, TOS); | 
| 3270   // if (object->IsSmi()) return object. | 2908   // if (object->IsSmi()) return object. | 
| 3271   __ test(eax, Immediate(kSmiTagMask)); | 2909   __ test(eax, Immediate(kSmiTagMask)); | 
| 3272   __ j(zero, &leave, taken); | 2910   __ j(zero, &leave, taken); | 
| 3273   // It is a heap object - get map. | 2911   // It is a heap object - get map. | 
| 3274   __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2912   __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 
| 3275   __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 2913   __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 
| 3276   // if (!object->IsJSValue()) return object. | 2914   // if (!object->IsJSValue()) return object. | 
| 3277   __ cmp(ebx, JS_VALUE_TYPE); | 2915   __ cmp(ebx, JS_VALUE_TYPE); | 
| 3278   __ j(not_equal, &leave, not_taken); | 2916   __ j(not_equal, &leave, not_taken); | 
| 3279   // Store the value. | 2917   // Store the value. | 
| 3280   __ mov(FieldOperand(eax, JSValue::kValueOffset), ecx); | 2918   __ mov(FieldOperand(eax, JSValue::kValueOffset), ecx); | 
| 3281   // Update the write barrier. | 2919   // Update the write barrier. | 
| 3282   __ RecordWrite(eax, JSValue::kValueOffset, ecx, ebx); | 2920   __ RecordWrite(eax, JSValue::kValueOffset, ecx, ebx); | 
| 3283   // Leave. | 2921   // Leave. | 
| 3284   __ bind(&leave); | 2922   __ bind(&leave); | 
| 3285   __ mov(ecx, TOS); | 2923   __ mov(ecx, TOS); | 
| 3286   __ pop(eax); | 2924   __ pop(eax); | 
| 3287   __ mov(TOS, ecx); | 2925   __ mov(TOS, ecx); | 
| 3288 } | 2926 } | 
| 3289 | 2927 | 
| 3290 | 2928 | 
| 3291 void Ia32CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { | 2929 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { | 
| 3292   ASSERT(args->length() == 1); | 2930   ASSERT(args->length() == 1); | 
| 3293 | 2931 | 
| 3294   // Load the key onto the stack and set register eax to the formal | 2932   // Load the key onto the stack and set register eax to the formal | 
| 3295   // parameters count for the currently executing function. | 2933   // parameters count for the currently executing function. | 
| 3296   Load(args->at(0)); | 2934   Load(args->at(0)); | 
| 3297   __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); | 2935   __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); | 
| 3298 | 2936 | 
| 3299   // Call the shared stub to get to arguments[key]. | 2937   // Call the shared stub to get to arguments[key]. | 
| 3300   ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); | 2938   ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); | 
| 3301   __ CallStub(&stub); | 2939   __ CallStub(&stub); | 
| 3302   __ mov(TOS, eax); | 2940   __ mov(TOS, eax); | 
| 3303 } | 2941 } | 
| 3304 | 2942 | 
| 3305 | 2943 | 
| 3306 void Ia32CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { | 2944 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { | 
| 3307   ASSERT(args->length() == 2); | 2945   ASSERT(args->length() == 2); | 
| 3308 | 2946 | 
| 3309   // Load the two objects into registers and perform the comparison. | 2947   // Load the two objects into registers and perform the comparison. | 
| 3310   Load(args->at(0)); | 2948   Load(args->at(0)); | 
| 3311   Load(args->at(1)); | 2949   Load(args->at(1)); | 
| 3312   __ pop(eax); | 2950   __ pop(eax); | 
| 3313   __ pop(ecx); | 2951   __ pop(ecx); | 
| 3314   __ cmp(eax, Operand(ecx)); | 2952   __ cmp(eax, Operand(ecx)); | 
| 3315   cc_reg_ = equal; | 2953   cc_reg_ = equal; | 
| 3316 } | 2954 } | 
| 3317 | 2955 | 
| 3318 | 2956 | 
| 3319 void Ia32CodeGenerator::VisitCallRuntime(CallRuntime* node) { | 2957 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { | 
| 3320   if (CheckForInlineRuntimeCall(node)) return; | 2958   if (CheckForInlineRuntimeCall(node)) return; | 
| 3321 | 2959 | 
| 3322   ZoneList<Expression*>* args = node->arguments(); | 2960   ZoneList<Expression*>* args = node->arguments(); | 
| 3323   Comment cmnt(masm_, "[ CallRuntime"); | 2961   Comment cmnt(masm_, "[ CallRuntime"); | 
| 3324   Runtime::Function* function = node->function(); | 2962   Runtime::Function* function = node->function(); | 
| 3325 | 2963 | 
| 3326   if (function == NULL) { | 2964   if (function == NULL) { | 
| 3327     // Prepare stack for calling JS runtime function. | 2965     // Prepare stack for calling JS runtime function. | 
| 3328     __ push(Immediate(node->name())); | 2966     __ push(Immediate(node->name())); | 
| 3329     // Push the builtins object found in the current global object. | 2967     // Push the builtins object found in the current global object. | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 3343     // Call the JS runtime function. | 2981     // Call the JS runtime function. | 
| 3344     Handle<Code> stub = ComputeCallInitialize(args->length()); | 2982     Handle<Code> stub = ComputeCallInitialize(args->length()); | 
| 3345     __ Set(eax, Immediate(args->length())); | 2983     __ Set(eax, Immediate(args->length())); | 
| 3346     __ call(stub, RelocInfo::CODE_TARGET); | 2984     __ call(stub, RelocInfo::CODE_TARGET); | 
| 3347     __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2985     __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 
| 3348     __ mov(TOS, eax); | 2986     __ mov(TOS, eax); | 
| 3349   } | 2987   } | 
| 3350 } | 2988 } | 
| 3351 | 2989 | 
| 3352 | 2990 | 
| 3353 void Ia32CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { | 2991 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { | 
| 3354   Comment cmnt(masm_, "[ UnaryOperation"); | 2992   Comment cmnt(masm_, "[ UnaryOperation"); | 
| 3355 | 2993 | 
| 3356   Token::Value op = node->op(); | 2994   Token::Value op = node->op(); | 
| 3357 | 2995 | 
| 3358   if (op == Token::NOT) { | 2996   if (op == Token::NOT) { | 
| 3359     LoadCondition(node->expression(), NOT_INSIDE_TYPEOF, | 2997     LoadCondition(node->expression(), NOT_INSIDE_TYPEOF, | 
| 3360                   false_target(), true_target(), true); | 2998                   false_target(), true_target(), true); | 
| 3361     cc_reg_ = NegateCondition(cc_reg_); | 2999     cc_reg_ = NegateCondition(cc_reg_); | 
| 3362 | 3000 | 
| 3363   } else if (op == Token::DELETE) { | 3001   } else if (op == Token::DELETE) { | 
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3552 void CountOperationDeferred::Generate() { | 3190 void CountOperationDeferred::Generate() { | 
| 3553   if (is_postfix_) { | 3191   if (is_postfix_) { | 
| 3554     RevertToNumberStub to_number_stub(is_increment_); | 3192     RevertToNumberStub to_number_stub(is_increment_); | 
| 3555     __ CallStub(&to_number_stub); | 3193     __ CallStub(&to_number_stub); | 
| 3556   } | 3194   } | 
| 3557   CounterOpStub stub(result_offset_, is_postfix_, is_increment_); | 3195   CounterOpStub stub(result_offset_, is_postfix_, is_increment_); | 
| 3558   __ CallStub(&stub); | 3196   __ CallStub(&stub); | 
| 3559 } | 3197 } | 
| 3560 | 3198 | 
| 3561 | 3199 | 
| 3562 void Ia32CodeGenerator::VisitCountOperation(CountOperation* node) { | 3200 void CodeGenerator::VisitCountOperation(CountOperation* node) { | 
| 3563   Comment cmnt(masm_, "[ CountOperation"); | 3201   Comment cmnt(masm_, "[ CountOperation"); | 
| 3564 | 3202 | 
| 3565   bool is_postfix = node->is_postfix(); | 3203   bool is_postfix = node->is_postfix(); | 
| 3566   bool is_increment = node->op() == Token::INC; | 3204   bool is_increment = node->op() == Token::INC; | 
| 3567 | 3205 | 
| 3568   Variable* var = node->expression()->AsVariableProxy()->AsVariable(); | 3206   Variable* var = node->expression()->AsVariableProxy()->AsVariable(); | 
| 3569   bool is_const = (var != NULL && var->mode() == Variable::CONST); | 3207   bool is_const = (var != NULL && var->mode() == Variable::CONST); | 
| 3570 | 3208 | 
| 3571   // Postfix: Make room for the result. | 3209   // Postfix: Make room for the result. | 
| 3572   if (is_postfix) __ push(Immediate(0)); | 3210   if (is_postfix) __ push(Immediate(0)); | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
| 3603     __ bind(deferred->exit()); | 3241     __ bind(deferred->exit()); | 
| 3604     __ push(eax);  // Push the new value to TOS | 3242     __ push(eax);  // Push the new value to TOS | 
| 3605     if (!is_const) target.SetValue(NOT_CONST_INIT); | 3243     if (!is_const) target.SetValue(NOT_CONST_INIT); | 
| 3606   } | 3244   } | 
| 3607 | 3245 | 
| 3608   // Postfix: Discard the new value and use the old. | 3246   // Postfix: Discard the new value and use the old. | 
| 3609   if (is_postfix) __ pop(eax); | 3247   if (is_postfix) __ pop(eax); | 
| 3610 } | 3248 } | 
| 3611 | 3249 | 
| 3612 | 3250 | 
| 3613 void Ia32CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { | 3251 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { | 
| 3614   Comment cmnt(masm_, "[ BinaryOperation"); | 3252   Comment cmnt(masm_, "[ BinaryOperation"); | 
| 3615   Token::Value op = node->op(); | 3253   Token::Value op = node->op(); | 
| 3616 | 3254 | 
| 3617   // According to ECMA-262 section 11.11, page 58, the binary logical | 3255   // According to ECMA-262 section 11.11, page 58, the binary logical | 
| 3618   // operators must yield the result of one of the two expressions | 3256   // operators must yield the result of one of the two expressions | 
| 3619   // before any ToBoolean() conversions. This means that the value | 3257   // before any ToBoolean() conversions. This means that the value | 
| 3620   // produced by a && or || operator is not necessarily a boolean. | 3258   // produced by a && or || operator is not necessarily a boolean. | 
| 3621 | 3259 | 
| 3622   // NOTE: If the left hand side produces a materialized value (not in | 3260   // NOTE: If the left hand side produces a materialized value (not in | 
| 3623   // the CC register), we force the right hand side to do the | 3261   // the CC register), we force the right hand side to do the | 
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3725 | 3363 | 
| 3726     } else { | 3364     } else { | 
| 3727       Load(node->left()); | 3365       Load(node->left()); | 
| 3728       Load(node->right()); | 3366       Load(node->right()); | 
| 3729       GenericBinaryOperation(node->op(), overwrite_mode); | 3367       GenericBinaryOperation(node->op(), overwrite_mode); | 
| 3730     } | 3368     } | 
| 3731   } | 3369   } | 
| 3732 } | 3370 } | 
| 3733 | 3371 | 
| 3734 | 3372 | 
| 3735 void Ia32CodeGenerator::VisitThisFunction(ThisFunction* node) { | 3373 void CodeGenerator::VisitThisFunction(ThisFunction* node) { | 
| 3736   __ push(FunctionOperand()); | 3374   __ push(FunctionOperand()); | 
| 3737 } | 3375 } | 
| 3738 | 3376 | 
| 3739 | 3377 | 
| 3740 class InstanceofStub: public CodeStub { | 3378 class InstanceofStub: public CodeStub { | 
| 3741  public: | 3379  public: | 
| 3742   InstanceofStub() { } | 3380   InstanceofStub() { } | 
| 3743 | 3381 | 
| 3744   void Generate(MacroAssembler* masm); | 3382   void Generate(MacroAssembler* masm); | 
| 3745 | 3383 | 
| 3746  private: | 3384  private: | 
| 3747   Major MajorKey() { return Instanceof; } | 3385   Major MajorKey() { return Instanceof; } | 
| 3748   int MinorKey() { return 0; } | 3386   int MinorKey() { return 0; } | 
| 3749 }; | 3387 }; | 
| 3750 | 3388 | 
| 3751 | 3389 | 
| 3752 void Ia32CodeGenerator::VisitCompareOperation(CompareOperation* node) { | 3390 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { | 
| 3753   Comment cmnt(masm_, "[ CompareOperation"); | 3391   Comment cmnt(masm_, "[ CompareOperation"); | 
| 3754 | 3392 | 
| 3755   // Get the expressions from the node. | 3393   // Get the expressions from the node. | 
| 3756   Expression* left = node->left(); | 3394   Expression* left = node->left(); | 
| 3757   Expression* right = node->right(); | 3395   Expression* right = node->right(); | 
| 3758   Token::Value op = node->op(); | 3396   Token::Value op = node->op(); | 
| 3759 | 3397 | 
| 3760   // NOTE: To make null checks efficient, we check if either left or | 3398   // NOTE: To make null checks efficient, we check if either left or | 
| 3761   // right is the literal 'null'. If so, we optimize the code by | 3399   // right is the literal 'null'. If so, we optimize the code by | 
| 3762   // inlining a null check instead of calling the (very) general | 3400   // inlining a null check instead of calling the (very) general | 
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3951     SmiComparison(cc, right->AsLiteral()->handle(), strict); | 3589     SmiComparison(cc, right->AsLiteral()->handle(), strict); | 
| 3952     return; | 3590     return; | 
| 3953   } | 3591   } | 
| 3954 | 3592 | 
| 3955   Load(left); | 3593   Load(left); | 
| 3956   Load(right); | 3594   Load(right); | 
| 3957   Comparison(cc, strict); | 3595   Comparison(cc, strict); | 
| 3958 } | 3596 } | 
| 3959 | 3597 | 
| 3960 | 3598 | 
| 3961 void Ia32CodeGenerator::RecordStatementPosition(Node* node) { | 3599 void CodeGenerator::RecordStatementPosition(Node* node) { | 
| 3962   if (FLAG_debug_info) { | 3600   if (FLAG_debug_info) { | 
| 3963     int pos = node->statement_pos(); | 3601     int pos = node->statement_pos(); | 
| 3964     if (pos != RelocInfo::kNoPosition) { | 3602     if (pos != RelocInfo::kNoPosition) { | 
| 3965       __ RecordStatementPosition(pos); | 3603       __ RecordStatementPosition(pos); | 
| 3966     } | 3604     } | 
| 3967   } | 3605   } | 
| 3968 } | 3606 } | 
| 3969 | 3607 | 
| 3970 | 3608 | 
| 3971 void Ia32CodeGenerator::EnterJSFrame() { | 3609 void CodeGenerator::EnterJSFrame() { | 
| 3972   __ push(ebp); | 3610   __ push(ebp); | 
| 3973   __ mov(ebp, Operand(esp)); | 3611   __ mov(ebp, Operand(esp)); | 
| 3974 | 3612 | 
| 3975   // Store the context and the function in the frame. | 3613   // Store the context and the function in the frame. | 
| 3976   __ push(esi); | 3614   __ push(esi); | 
| 3977   __ push(edi); | 3615   __ push(edi); | 
| 3978 | 3616 | 
| 3979   // Clear the function slot when generating debug code. | 3617   // Clear the function slot when generating debug code. | 
| 3980   if (FLAG_debug_code) { | 3618   if (FLAG_debug_code) { | 
| 3981     __ Set(edi, Immediate(reinterpret_cast<int>(kZapValue))); | 3619     __ Set(edi, Immediate(reinterpret_cast<int>(kZapValue))); | 
| 3982   } | 3620   } | 
| 3983 } | 3621 } | 
| 3984 | 3622 | 
| 3985 | 3623 | 
| 3986 void Ia32CodeGenerator::ExitJSFrame() { | 3624 void CodeGenerator::ExitJSFrame() { | 
| 3987   // Record the location of the JS exit code for patching when setting | 3625   // Record the location of the JS exit code for patching when setting | 
| 3988   // break point. | 3626   // break point. | 
| 3989   __ RecordJSReturn(); | 3627   __ RecordJSReturn(); | 
| 3990 | 3628 | 
| 3991   // Avoid using the leave instruction here, because it is too | 3629   // Avoid using the leave instruction here, because it is too | 
| 3992   // short. We need the return sequence to be a least the size of a | 3630   // short. We need the return sequence to be a least the size of a | 
| 3993   // call instruction to support patching the exit code in the | 3631   // call instruction to support patching the exit code in the | 
| 3994   // debugger. See VisitReturnStatement for the full return sequence. | 3632   // debugger. See VisitReturnStatement for the full return sequence. | 
| 3995   __ mov(esp, Operand(ebp)); | 3633   __ mov(esp, Operand(ebp)); | 
| 3996   __ pop(ebp); | 3634   __ pop(ebp); | 
| (...skipping 1339 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5336   __ ret(2 * kPointerSize); | 4974   __ ret(2 * kPointerSize); | 
| 5337 | 4975 | 
| 5338   // Slow-case: Go through the JavaScript implementation. | 4976   // Slow-case: Go through the JavaScript implementation. | 
| 5339   __ bind(&slow); | 4977   __ bind(&slow); | 
| 5340   __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 4978   __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 
| 5341 } | 4979 } | 
| 5342 | 4980 | 
| 5343 | 4981 | 
| 5344 #undef __ | 4982 #undef __ | 
| 5345 | 4983 | 
| 5346 // ----------------------------------------------------------------------------- |  | 
| 5347 // CodeGenerator interfaces |  | 
| 5348 |  | 
| 5349 // MakeCode() is just a wrapper for CodeGenerator::MakeCode() |  | 
| 5350 // so we don't have to expose the entire CodeGenerator class in |  | 
| 5351 // the .h file. |  | 
| 5352 Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun, |  | 
| 5353                                      Handle<Script> script, |  | 
| 5354                                      bool is_eval) { |  | 
| 5355   Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval); |  | 
| 5356   if (!code.is_null()) { |  | 
| 5357     Counters::total_compiled_code_size.Increment(code->instruction_size()); |  | 
| 5358   } |  | 
| 5359   return code; |  | 
| 5360 } |  | 
| 5361 |  | 
| 5362 |  | 
| 5363 } }  // namespace v8::internal | 4984 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|