| 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 25 matching lines...) Expand all Loading... |
| 36 class DeferredCode; | 36 class DeferredCode; |
| 37 | 37 |
| 38 // Mode to overwrite BinaryExpression values. | 38 // Mode to overwrite BinaryExpression values. |
| 39 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT }; | 39 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT }; |
| 40 | 40 |
| 41 enum InitState { CONST_INIT, NOT_CONST_INIT }; | 41 enum InitState { CONST_INIT, NOT_CONST_INIT }; |
| 42 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; | 42 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; |
| 43 | 43 |
| 44 | 44 |
| 45 // ------------------------------------------------------------------------- | 45 // ------------------------------------------------------------------------- |
| 46 // Virtual frame | |
| 47 | |
| 48 class VirtualFrame BASE_EMBEDDED { | |
| 49 public: | |
| 50 explicit VirtualFrame(CodeGenerator* cgen); | |
| 51 | |
| 52 void Enter(); | |
| 53 void Exit(); | |
| 54 | |
| 55 void AllocateLocals(); | |
| 56 | |
| 57 Operand Top() const { return Operand(esp, 0); } | |
| 58 | |
| 59 Operand Element(int index) const { | |
| 60 return Operand(esp, index * kPointerSize); | |
| 61 } | |
| 62 | |
| 63 Operand Local(int index) const { | |
| 64 ASSERT(0 <= index && index < frame_local_count_); | |
| 65 return Operand(ebp, kLocal0Offset - index * kPointerSize); | |
| 66 } | |
| 67 | |
| 68 Operand Function() const { return Operand(ebp, kFunctionOffset); } | |
| 69 | |
| 70 Operand Context() const { return Operand(ebp, kContextOffset); } | |
| 71 | |
| 72 Operand Parameter(int index) const { | |
| 73 ASSERT(-1 <= index && index < parameter_count_); | |
| 74 return Operand(ebp, (1 + parameter_count_ - index) * kPointerSize); | |
| 75 } | |
| 76 | |
| 77 Operand Receiver() const { return Parameter(-1); } | |
| 78 | |
| 79 inline void Drop(int count); | |
| 80 | |
| 81 inline void Pop(); | |
| 82 inline void Pop(Register reg); | |
| 83 inline void Pop(Operand operand); | |
| 84 | |
| 85 inline void Push(Register reg); | |
| 86 inline void Push(Operand operand); | |
| 87 inline void Push(Immediate immediate); | |
| 88 | |
| 89 private: | |
| 90 static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; | |
| 91 static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset; | |
| 92 static const int kContextOffset = StandardFrameConstants::kContextOffset; | |
| 93 | |
| 94 MacroAssembler* masm_; | |
| 95 int frame_local_count_; | |
| 96 int parameter_count_; | |
| 97 }; | |
| 98 | |
| 99 | |
| 100 // ------------------------------------------------------------------------- | |
| 101 // Reference support | 46 // Reference support |
| 102 | 47 |
| 103 // A reference is a C++ stack-allocated object that keeps an ECMA | 48 // A reference is a C++ stack-allocated object that keeps an ECMA |
| 104 // reference on the execution stack while in scope. For variables | 49 // reference on the execution stack while in scope. For variables |
| 105 // the reference is empty, indicating that it isn't necessary to | 50 // the reference is empty, indicating that it isn't necessary to |
| 106 // store state on the stack for keeping track of references to those. | 51 // store state on the stack for keeping track of references to those. |
| 107 // For properties, we keep either one (named) or two (indexed) values | 52 // For properties, we keep either one (named) or two (indexed) values |
| 108 // on the execution stack to represent the reference. | 53 // on the execution stack to represent the reference. |
| 109 | 54 |
| 110 class Reference BASE_EMBEDDED { | 55 class Reference BASE_EMBEDDED { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 CodeGenerator* cgen_; | 91 CodeGenerator* cgen_; |
| 147 Expression* expression_; | 92 Expression* expression_; |
| 148 Type type_; | 93 Type type_; |
| 149 }; | 94 }; |
| 150 | 95 |
| 151 | 96 |
| 152 // ------------------------------------------------------------------------- | 97 // ------------------------------------------------------------------------- |
| 153 // Code generation state | 98 // Code generation state |
| 154 | 99 |
| 155 // The state is passed down the AST by the code generator (and back up, in | 100 // The state is passed down the AST by the code generator (and back up, in |
| 156 // the form of the state of the label pair). It is threaded through the | 101 // the form of the state of the jump target pair). It is threaded through |
| 157 // call stack. Constructing a state implicitly pushes it on the owning code | 102 // the call stack. Constructing a state implicitly pushes it on the owning |
| 158 // generator's stack of states, and destroying one implicitly pops it. | 103 // code generator's stack of states, and destroying one implicitly pops it. |
| 104 // |
| 105 // The code generator state is only used for expressions, so statements have |
| 106 // the initial state. |
| 159 | 107 |
| 160 class CodeGenState BASE_EMBEDDED { | 108 class CodeGenState BASE_EMBEDDED { |
| 161 public: | 109 public: |
| 162 // Create an initial code generator state. Destroying the initial state | 110 // Create an initial code generator state. Destroying the initial state |
| 163 // leaves the code generator with a NULL state. | 111 // leaves the code generator with a NULL state. |
| 164 explicit CodeGenState(CodeGenerator* owner); | 112 explicit CodeGenState(CodeGenerator* owner); |
| 165 | 113 |
| 166 // Create a code generator state based on a code generator's current | 114 // Create a code generator state based on a code generator's current |
| 167 // state. The new state has its own access type and pair of branch | 115 // state. The new state may or may not be inside a typeof, and has its |
| 168 // labels, and no reference. | 116 // own pair of branch targets. |
| 169 CodeGenState(CodeGenerator* owner, | 117 CodeGenState(CodeGenerator* owner, |
| 170 TypeofState typeof_state, | 118 TypeofState typeof_state, |
| 171 Label* true_target, | 119 JumpTarget* true_target, |
| 172 Label* false_target); | 120 JumpTarget* false_target); |
| 173 | 121 |
| 174 // Destroy a code generator state and restore the owning code generator's | 122 // Destroy a code generator state and restore the owning code generator's |
| 175 // previous state. | 123 // previous state. |
| 176 ~CodeGenState(); | 124 ~CodeGenState(); |
| 177 | 125 |
| 126 // Accessors for the state. |
| 178 TypeofState typeof_state() const { return typeof_state_; } | 127 TypeofState typeof_state() const { return typeof_state_; } |
| 179 Label* true_target() const { return true_target_; } | 128 JumpTarget* true_target() const { return true_target_; } |
| 180 Label* false_target() const { return false_target_; } | 129 JumpTarget* false_target() const { return false_target_; } |
| 181 | 130 |
| 182 private: | 131 private: |
| 132 // The owning code generator. |
| 183 CodeGenerator* owner_; | 133 CodeGenerator* owner_; |
| 134 |
| 135 // A flag indicating whether we are compiling the immediate subexpression |
| 136 // of a typeof expression. |
| 184 TypeofState typeof_state_; | 137 TypeofState typeof_state_; |
| 185 Label* true_target_; | 138 |
| 186 Label* false_target_; | 139 // A pair of jump targets in case the expression has a control-flow |
| 140 // effect. |
| 141 JumpTarget* true_target_; |
| 142 JumpTarget* false_target_; |
| 143 |
| 144 // The previous state of the owning code generator, restored when |
| 145 // this state is destroyed. |
| 187 CodeGenState* previous_; | 146 CodeGenState* previous_; |
| 188 }; | 147 }; |
| 189 | 148 |
| 190 | 149 |
| 191 | 150 |
| 192 | 151 |
| 193 // ------------------------------------------------------------------------- | 152 // ------------------------------------------------------------------------- |
| 194 // CodeGenerator | 153 // CodeGenerator |
| 195 | 154 |
| 196 class CodeGenerator: public Visitor { | 155 class CodeGenerator: public Visitor { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 208 int end_position, | 167 int end_position, |
| 209 bool is_expression, | 168 bool is_expression, |
| 210 bool is_toplevel, | 169 bool is_toplevel, |
| 211 Handle<Script> script); | 170 Handle<Script> script); |
| 212 | 171 |
| 213 // Accessors | 172 // Accessors |
| 214 MacroAssembler* masm() { return masm_; } | 173 MacroAssembler* masm() { return masm_; } |
| 215 | 174 |
| 216 VirtualFrame* frame() const { return frame_; } | 175 VirtualFrame* frame() const { return frame_; } |
| 217 | 176 |
| 177 void set_frame(VirtualFrame* frame) { frame_ = frame; } |
| 178 |
| 179 void delete_frame() { |
| 180 delete frame_; |
| 181 frame_ = NULL; |
| 182 } |
| 183 |
| 218 CodeGenState* state() { return state_; } | 184 CodeGenState* state() { return state_; } |
| 219 void set_state(CodeGenState* state) { state_ = state; } | 185 void set_state(CodeGenState* state) { state_ = state; } |
| 220 | 186 |
| 221 void AddDeferred(DeferredCode* code) { deferred_.Add(code); } | 187 void AddDeferred(DeferredCode* code) { deferred_.Add(code); } |
| 222 | 188 |
| 223 private: | 189 private: |
| 224 // Construction/Destruction | 190 // Construction/Destruction |
| 225 CodeGenerator(int buffer_size, Handle<Script> script, bool is_eval); | 191 CodeGenerator(int buffer_size, Handle<Script> script, bool is_eval); |
| 226 virtual ~CodeGenerator() { delete masm_; } | 192 virtual ~CodeGenerator() { delete masm_; } |
| 227 | 193 |
| 228 // Accessors | 194 // Accessors |
| 229 Scope* scope() const { return scope_; } | 195 Scope* scope() const { return scope_; } |
| 230 | 196 |
| 231 void ProcessDeferred(); | 197 void ProcessDeferred(); |
| 232 | 198 |
| 233 bool is_eval() { return is_eval_; } | 199 bool is_eval() { return is_eval_; } |
| 234 | 200 |
| 235 // State | 201 // State |
| 236 bool has_cc() const { return cc_reg_ >= 0; } | 202 bool has_cc() const { return cc_reg_ >= 0; } |
| 237 TypeofState typeof_state() const { return state_->typeof_state(); } | 203 TypeofState typeof_state() const { return state_->typeof_state(); } |
| 238 Label* true_target() const { return state_->true_target(); } | 204 JumpTarget* true_target() const { return state_->true_target(); } |
| 239 Label* false_target() const { return state_->false_target(); } | 205 JumpTarget* false_target() const { return state_->false_target(); } |
| 240 | 206 |
| 241 // Track loop nesting level. | 207 // Track loop nesting level. |
| 242 int loop_nesting() const { return loop_nesting_; } | 208 int loop_nesting() const { return loop_nesting_; } |
| 243 void IncrementLoopNesting() { loop_nesting_++; } | 209 void IncrementLoopNesting() { loop_nesting_++; } |
| 244 void DecrementLoopNesting() { loop_nesting_--; } | 210 void DecrementLoopNesting() { loop_nesting_--; } |
| 245 | 211 |
| 246 | 212 |
| 247 // Node visitors. | 213 // Node visitors. |
| 214 void VisitStatements(ZoneList<Statement*>* statements); |
| 215 |
| 248 #define DEF_VISIT(type) \ | 216 #define DEF_VISIT(type) \ |
| 249 void Visit##type(type* node); | 217 void Visit##type(type* node); |
| 250 NODE_LIST(DEF_VISIT) | 218 NODE_LIST(DEF_VISIT) |
| 251 #undef DEF_VISIT | 219 #undef DEF_VISIT |
| 252 | 220 |
| 253 // Main code generation function | 221 // Main code generation function |
| 254 void GenCode(FunctionLiteral* fun); | 222 void GenCode(FunctionLiteral* fun); |
| 255 | 223 |
| 256 // The following are used by class Reference. | 224 // The following are used by class Reference. |
| 257 void LoadReference(Reference* ref); | 225 void LoadReference(Reference* ref); |
| 258 void UnloadReference(Reference* ref); | 226 void UnloadReference(Reference* ref); |
| 259 | 227 |
| 260 Operand ContextOperand(Register context, int index) const { | 228 Operand ContextOperand(Register context, int index) const { |
| 261 return Operand(context, Context::SlotOffset(index)); | 229 return Operand(context, Context::SlotOffset(index)); |
| 262 } | 230 } |
| 263 | 231 |
| 264 Operand SlotOperand(Slot* slot, Register tmp); | 232 Operand SlotOperand(Slot* slot, Register tmp); |
| 265 | 233 |
| 266 | 234 |
| 267 // Expressions | 235 // Expressions |
| 268 Operand GlobalObject() const { | 236 Operand GlobalObject() const { |
| 269 return ContextOperand(esi, Context::GLOBAL_INDEX); | 237 return ContextOperand(esi, Context::GLOBAL_INDEX); |
| 270 } | 238 } |
| 271 | 239 |
| 272 void LoadCondition(Expression* x, | 240 void LoadCondition(Expression* x, |
| 273 TypeofState typeof_state, | 241 TypeofState typeof_state, |
| 274 Label* true_target, | 242 JumpTarget* true_target, |
| 275 Label* false_target, | 243 JumpTarget* false_target, |
| 276 bool force_cc); | 244 bool force_cc); |
| 277 void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF); | 245 void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF); |
| 278 void LoadGlobal(); | 246 void LoadGlobal(); |
| 279 void LoadGlobalReceiver(Register scratch); | 247 void LoadGlobalReceiver(Register scratch); |
| 280 | 248 |
| 281 // Read a value from a slot and leave it on top of the expression stack. | 249 // Read a value from a slot and leave it on top of the expression stack. |
| 282 void LoadFromSlot(Slot* slot, TypeofState typeof_state); | 250 void LoadFromSlot(Slot* slot, TypeofState typeof_state); |
| 283 | 251 |
| 284 // Special code for typeof expressions: Unfortunately, we must | 252 // Special code for typeof expressions: Unfortunately, we must |
| 285 // be careful when loading the expression in 'typeof' | 253 // be careful when loading the expression in 'typeof' |
| 286 // expressions. We are not allowed to throw reference errors for | 254 // expressions. We are not allowed to throw reference errors for |
| 287 // non-existing properties of the global object, so we must make it | 255 // non-existing properties of the global object, so we must make it |
| 288 // look like an explicit property access, instead of an access | 256 // look like an explicit property access, instead of an access |
| 289 // through the context chain. | 257 // through the context chain. |
| 290 void LoadTypeofExpression(Expression* x); | 258 void LoadTypeofExpression(Expression* x); |
| 291 | 259 |
| 292 void ToBoolean(Label* true_target, Label* false_target); | 260 void ToBoolean(JumpTarget* true_target, JumpTarget* false_target); |
| 293 | 261 |
| 294 void GenericBinaryOperation(Token::Value op, | 262 void GenericBinaryOperation(Token::Value op, |
| 295 StaticType* type, | 263 StaticType* type, |
| 296 const OverwriteMode overwrite_mode = NO_OVERWRITE); | 264 const OverwriteMode overwrite_mode = NO_OVERWRITE); |
| 297 | 265 |
| 298 void Comparison(Condition cc, bool strict = false); | 266 void Comparison(Condition cc, bool strict = false); |
| 299 | 267 |
| 300 // Inline small integer literals. To prevent long attacker-controlled byte | 268 // Inline small integer literals. To prevent long attacker-controlled byte |
| 301 // sequences, we only inline small Smis. | 269 // sequences, we only inline small Smis. |
| 302 static const int kMaxSmiInlinedBits = 16; | 270 static const int kMaxSmiInlinedBits = 16; |
| 303 bool IsInlineSmi(Literal* literal); | 271 bool IsInlineSmi(Literal* literal); |
| 304 void SmiComparison(Condition cc, Handle<Object> value, bool strict = false); | 272 void SmiComparison(Condition cc, Handle<Object> value, bool strict = false); |
| 305 void SmiOperation(Token::Value op, | 273 void SmiOperation(Token::Value op, |
| 306 StaticType* type, | 274 StaticType* type, |
| 307 Handle<Object> value, | 275 Handle<Object> value, |
| 308 bool reversed, | 276 bool reversed, |
| 309 OverwriteMode overwrite_mode); | 277 OverwriteMode overwrite_mode); |
| 310 | 278 |
| 311 void CallWithArguments(ZoneList<Expression*>* arguments, int position); | 279 void CallWithArguments(ZoneList<Expression*>* arguments, int position); |
| 312 | 280 |
| 313 // Control flow | 281 // Control flow |
| 314 void Branch(bool if_true, Label* L); | 282 void Branch(bool if_true, JumpTarget* target); |
| 315 void CheckStack(); | 283 void CheckStack(); |
| 316 void CleanStack(int num_bytes); | 284 void CleanStack(int num_bytes); |
| 317 | 285 |
| 318 bool CheckForInlineRuntimeCall(CallRuntime* node); | 286 bool CheckForInlineRuntimeCall(CallRuntime* node); |
| 319 Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node); | 287 Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node); |
| 320 void ProcessDeclarations(ZoneList<Declaration*>* declarations); | 288 void ProcessDeclarations(ZoneList<Declaration*>* declarations); |
| 321 | 289 |
| 322 Handle<Code> ComputeCallInitialize(int argc); | 290 Handle<Code> ComputeCallInitialize(int argc); |
| 323 | 291 |
| 324 // Declare global variables and functions in the given array of | 292 // Declare global variables and functions in the given array of |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 // is optimal compared to the default code generated for a switch statement | 340 // is optimal compared to the default code generated for a switch statement |
| 373 // on that platform. | 341 // on that platform. |
| 374 int FastCaseSwitchMinCaseCount(); | 342 int FastCaseSwitchMinCaseCount(); |
| 375 | 343 |
| 376 // Allocate a jump table and create code to jump through it. | 344 // Allocate a jump table and create code to jump through it. |
| 377 // Should call GenerateFastCaseSwitchCases to generate the code for | 345 // Should call GenerateFastCaseSwitchCases to generate the code for |
| 378 // all the cases at the appropriate point. | 346 // all the cases at the appropriate point. |
| 379 void GenerateFastCaseSwitchJumpTable(SwitchStatement* node, | 347 void GenerateFastCaseSwitchJumpTable(SwitchStatement* node, |
| 380 int min_index, | 348 int min_index, |
| 381 int range, | 349 int range, |
| 382 Label* fail_label, | 350 JumpTarget* fail_label, |
| 383 Vector<Label*> case_targets, | 351 Vector<JumpTarget*> case_targets, |
| 384 Vector<Label> case_labels); | 352 Vector<JumpTarget> case_labels); |
| 385 | 353 |
| 386 // Generate the code for cases for the fast case switch. | 354 // Generate the code for cases for the fast case switch. |
| 387 // Called by GenerateFastCaseSwitchJumpTable. | 355 // Called by GenerateFastCaseSwitchJumpTable. |
| 388 void GenerateFastCaseSwitchCases(SwitchStatement* node, | 356 void GenerateFastCaseSwitchCases(SwitchStatement* node, |
| 389 Vector<Label> case_labels); | 357 Vector<JumpTarget> case_labels, |
| 358 JumpTarget* table_start); |
| 390 | 359 |
| 391 // Fast support for constant-Smi switches. | 360 // Fast support for constant-Smi switches. |
| 392 void GenerateFastCaseSwitchStatement(SwitchStatement* node, | 361 void GenerateFastCaseSwitchStatement(SwitchStatement* node, |
| 393 int min_index, | 362 int min_index, |
| 394 int range, | 363 int range, |
| 395 int default_index); | 364 int default_index); |
| 396 | 365 |
| 397 // Fast support for constant-Smi switches. Tests whether switch statement | 366 // Fast support for constant-Smi switches. Tests whether switch statement |
| 398 // permits optimization and calls GenerateFastCaseSwitch if it does. | 367 // permits optimization and calls GenerateFastCaseSwitch if it does. |
| 399 // Returns true if the fast-case switch was generated, and false if not. | 368 // Returns true if the fast-case switch was generated, and false if not. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 414 | 383 |
| 415 // Code generation state | 384 // Code generation state |
| 416 Scope* scope_; | 385 Scope* scope_; |
| 417 VirtualFrame* frame_; | 386 VirtualFrame* frame_; |
| 418 Condition cc_reg_; | 387 Condition cc_reg_; |
| 419 CodeGenState* state_; | 388 CodeGenState* state_; |
| 420 bool is_inside_try_; | 389 bool is_inside_try_; |
| 421 int break_stack_height_; | 390 int break_stack_height_; |
| 422 int loop_nesting_; | 391 int loop_nesting_; |
| 423 | 392 |
| 424 // Labels | 393 // Jump targets. |
| 425 Label function_return_; | 394 // The target of the return from the function. |
| 395 JumpTarget function_return_; |
| 396 |
| 397 // True if the function return is shadowed (ie, jumping to the target |
| 398 // function_return_ does not jump to the true function return, but rather |
| 399 // to some unlinking code). |
| 400 bool function_return_is_shadowed_; |
| 426 | 401 |
| 427 friend class VirtualFrame; | 402 friend class VirtualFrame; |
| 403 friend class JumpTarget; |
| 428 friend class Reference; | 404 friend class Reference; |
| 429 | 405 |
| 430 DISALLOW_COPY_AND_ASSIGN(CodeGenerator); | 406 DISALLOW_COPY_AND_ASSIGN(CodeGenerator); |
| 431 }; | 407 }; |
| 432 | 408 |
| 433 | 409 |
| 434 } } // namespace v8::internal | 410 } } // namespace v8::internal |
| 435 | 411 |
| 436 #endif // V8_CODEGEN_IA32_H_ | 412 #endif // V8_CODEGEN_IA32_H_ |
| OLD | NEW |