00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef V8_CODEGEN_IA32_H_
00029 #define V8_CODEGEN_IA32_H_
00030
00031 #include "scopes.h"
00032
00033 namespace v8 { namespace internal {
00034
00035
00036 class DeferredCode;
00037
00038
00039 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
00040
00041 enum InitState { CONST_INIT, NOT_CONST_INIT };
00042 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
00043
00044
00045
00046
00047
00048 class VirtualFrame BASE_EMBEDDED {
00049 public:
00050 explicit VirtualFrame(CodeGenerator* cgen);
00051
00052 void Enter();
00053 void Exit();
00054
00055 void AllocateLocals();
00056
00057 Operand Top() const { return Operand(esp, 0); }
00058
00059 Operand Element(int index) const {
00060 return Operand(esp, index * kPointerSize);
00061 }
00062
00063 Operand Local(int index) const {
00064 ASSERT(0 <= index && index < frame_local_count_);
00065 return Operand(ebp, kLocal0Offset - index * kPointerSize);
00066 }
00067
00068 Operand Function() const { return Operand(ebp, kFunctionOffset); }
00069
00070 Operand Context() const { return Operand(ebp, kContextOffset); }
00071
00072 Operand Parameter(int index) const {
00073 ASSERT(-1 <= index && index < parameter_count_);
00074 return Operand(ebp, (1 + parameter_count_ - index) * kPointerSize);
00075 }
00076
00077 Operand Receiver() const { return Parameter(-1); }
00078
00079 inline void Drop(int count);
00080
00081 inline void Pop();
00082 inline void Pop(Register reg);
00083 inline void Pop(Operand operand);
00084
00085 inline void Push(Register reg);
00086 inline void Push(Operand operand);
00087 inline void Push(Immediate immediate);
00088
00089 private:
00090 static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
00091 static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;
00092 static const int kContextOffset = StandardFrameConstants::kContextOffset;
00093
00094 MacroAssembler* masm_;
00095 int frame_local_count_;
00096 int parameter_count_;
00097 };
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 class Reference BASE_EMBEDDED {
00111 public:
00112
00113 enum Type { ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
00114 Reference(CodeGenerator* cgen, Expression* expression);
00115 ~Reference();
00116
00117 Expression* expression() const { return expression_; }
00118 Type type() const { return type_; }
00119 void set_type(Type value) {
00120 ASSERT(type_ == ILLEGAL);
00121 type_ = value;
00122 }
00123
00124
00125 int size() const { return type_; }
00126
00127 bool is_illegal() const { return type_ == ILLEGAL; }
00128 bool is_slot() const { return type_ == SLOT; }
00129 bool is_property() const { return type_ == NAMED || type_ == KEYED; }
00130
00131
00132 Handle<String> GetName();
00133
00134
00135
00136
00137 void GetValue(TypeofState typeof_state);
00138
00139
00140
00141
00142
00143 void SetValue(InitState init_state);
00144
00145 private:
00146 CodeGenerator* cgen_;
00147 Expression* expression_;
00148 Type type_;
00149 };
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 class CodeGenState BASE_EMBEDDED {
00161 public:
00162
00163
00164 explicit CodeGenState(CodeGenerator* owner);
00165
00166
00167
00168
00169 CodeGenState(CodeGenerator* owner,
00170 TypeofState typeof_state,
00171 Label* true_target,
00172 Label* false_target);
00173
00174
00175
00176 ~CodeGenState();
00177
00178 TypeofState typeof_state() const { return typeof_state_; }
00179 Label* true_target() const { return true_target_; }
00180 Label* false_target() const { return false_target_; }
00181
00182 private:
00183 CodeGenerator* owner_;
00184 TypeofState typeof_state_;
00185 Label* true_target_;
00186 Label* false_target_;
00187 CodeGenState* previous_;
00188 };
00189
00190
00191
00192
00193
00194
00195
00196 class CodeGenerator: public Visitor {
00197 public:
00198
00199
00200 static Handle<Code> MakeCode(FunctionLiteral* fun,
00201 Handle<Script> script,
00202 bool is_eval);
00203
00204 static void SetFunctionInfo(Handle<JSFunction> fun,
00205 int length,
00206 int function_token_position,
00207 int start_position,
00208 int end_position,
00209 bool is_expression,
00210 bool is_toplevel,
00211 Handle<Script> script);
00212
00213
00214 MacroAssembler* masm() { return masm_; }
00215
00216 VirtualFrame* frame() const { return frame_; }
00217
00218 CodeGenState* state() { return state_; }
00219 void set_state(CodeGenState* state) { state_ = state; }
00220
00221 void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
00222
00223 private:
00224
00225 CodeGenerator(int buffer_size, Handle<Script> script, bool is_eval);
00226 virtual ~CodeGenerator() { delete masm_; }
00227
00228
00229 Scope* scope() const { return scope_; }
00230
00231 void ProcessDeferred();
00232
00233 bool is_eval() { return is_eval_; }
00234
00235
00236 bool has_cc() const { return cc_reg_ >= 0; }
00237 TypeofState typeof_state() const { return state_->typeof_state(); }
00238 Label* true_target() const { return state_->true_target(); }
00239 Label* false_target() const { return state_->false_target(); }
00240
00241
00242 int loop_nesting() const { return loop_nesting_; }
00243 void IncrementLoopNesting() { loop_nesting_++; }
00244 void DecrementLoopNesting() { loop_nesting_--; }
00245
00246
00247
00248 #define DEF_VISIT(type) \
00249 void Visit##type(type* node);
00250 NODE_LIST(DEF_VISIT)
00251 #undef DEF_VISIT
00252
00253
00254 void GenCode(FunctionLiteral* fun);
00255
00256
00257 void LoadReference(Reference* ref);
00258 void UnloadReference(Reference* ref);
00259
00260 Operand ContextOperand(Register context, int index) const {
00261 return Operand(context, Context::SlotOffset(index));
00262 }
00263
00264 Operand SlotOperand(Slot* slot, Register tmp);
00265
00266
00267
00268 Operand GlobalObject() const {
00269 return ContextOperand(esi, Context::GLOBAL_INDEX);
00270 }
00271
00272 void LoadCondition(Expression* x,
00273 TypeofState typeof_state,
00274 Label* true_target,
00275 Label* false_target,
00276 bool force_cc);
00277 void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF);
00278 void LoadGlobal();
00279 void LoadGlobalReceiver(Register scratch);
00280
00281
00282 void LoadFromSlot(Slot* slot, TypeofState typeof_state);
00283
00284
00285
00286
00287
00288
00289
00290 void LoadTypeofExpression(Expression* x);
00291
00292 void ToBoolean(Label* true_target, Label* false_target);
00293
00294 void GenericBinaryOperation(Token::Value op,
00295 StaticType* type,
00296 const OverwriteMode overwrite_mode = NO_OVERWRITE);
00297
00298 void Comparison(Condition cc, bool strict = false);
00299
00300
00301
00302 static const int kMaxSmiInlinedBits = 16;
00303 bool IsInlineSmi(Literal* literal);
00304 void SmiComparison(Condition cc, Handle<Object> value, bool strict = false);
00305 void SmiOperation(Token::Value op,
00306 StaticType* type,
00307 Handle<Object> value,
00308 bool reversed,
00309 OverwriteMode overwrite_mode);
00310
00311 void CallWithArguments(ZoneList<Expression*>* arguments, int position);
00312
00313
00314 void Branch(bool if_true, Label* L);
00315 void CheckStack();
00316 void CleanStack(int num_bytes);
00317
00318 bool CheckForInlineRuntimeCall(CallRuntime* node);
00319 Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
00320 void ProcessDeclarations(ZoneList<Declaration*>* declarations);
00321
00322 Handle<Code> ComputeCallInitialize(int argc);
00323
00324
00325
00326 void DeclareGlobals(Handle<FixedArray> pairs);
00327
00328
00329 void InstantiateBoilerplate(Handle<JSFunction> boilerplate);
00330
00331
00332 void GenerateIsSmi(ZoneList<Expression*>* args);
00333 void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
00334 void GenerateIsArray(ZoneList<Expression*>* args);
00335
00336
00337 void GenerateArgumentsLength(ZoneList<Expression*>* args);
00338 void GenerateArgumentsAccess(ZoneList<Expression*>* args);
00339
00340
00341 void GenerateValueOf(ZoneList<Expression*>* args);
00342 void GenerateSetValueOf(ZoneList<Expression*>* args);
00343
00344
00345 void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
00346
00347
00348 void GenerateObjectEquals(ZoneList<Expression*>* args);
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 static const int kFastSwitchMaxOverheadFactor = 5;
00359
00360
00361
00362 static const int kFastSwitchMinCaseCount = 5;
00363
00364
00365
00366
00367
00368 int FastCaseSwitchMaxOverheadFactor();
00369
00370
00371
00372
00373
00374 int FastCaseSwitchMinCaseCount();
00375
00376
00377
00378
00379 void GenerateFastCaseSwitchJumpTable(SwitchStatement* node,
00380 int min_index,
00381 int range,
00382 Label* fail_label,
00383 Vector<Label*> case_targets,
00384 Vector<Label> case_labels);
00385
00386
00387
00388 void GenerateFastCaseSwitchCases(SwitchStatement* node,
00389 Vector<Label> case_labels);
00390
00391
00392 void GenerateFastCaseSwitchStatement(SwitchStatement* node,
00393 int min_index,
00394 int range,
00395 int default_index);
00396
00397
00398
00399
00400 bool TryGenerateFastCaseSwitchStatement(SwitchStatement* node);
00401
00402
00403
00404
00405
00406 void RecordStatementPosition(Node* node);
00407
00408 bool is_eval_;
00409 Handle<Script> script_;
00410 List<DeferredCode*> deferred_;
00411
00412
00413 MacroAssembler* masm_;
00414
00415
00416 Scope* scope_;
00417 VirtualFrame* frame_;
00418 Condition cc_reg_;
00419 CodeGenState* state_;
00420 bool is_inside_try_;
00421 int break_stack_height_;
00422 int loop_nesting_;
00423
00424
00425 Label function_return_;
00426
00427 friend class VirtualFrame;
00428 friend class Reference;
00429
00430 DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
00431 };
00432
00433
00434 } }
00435
00436 #endif // V8_CODEGEN_IA32_H_