OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 }; | 78 }; |
79 | 79 |
80 explicit FullCodeGenerator(MacroAssembler* masm) | 80 explicit FullCodeGenerator(MacroAssembler* masm) |
81 : masm_(masm), | 81 : masm_(masm), |
82 info_(NULL), | 82 info_(NULL), |
83 scope_(NULL), | 83 scope_(NULL), |
84 nesting_stack_(NULL), | 84 nesting_stack_(NULL), |
85 loop_depth_(0), | 85 loop_depth_(0), |
86 context_(NULL), | 86 context_(NULL), |
87 bailout_entries_(0), | 87 bailout_entries_(0), |
88 stack_checks_(2), // There's always at least one. | 88 stack_checks_(2) { // There's always at least one. |
89 forward_bailout_stack_(NULL), | |
90 forward_bailout_pending_(NULL) { | |
91 } | 89 } |
92 | 90 |
93 static bool MakeCode(CompilationInfo* info); | 91 static bool MakeCode(CompilationInfo* info); |
94 | 92 |
95 void Generate(CompilationInfo* info); | 93 void Generate(CompilationInfo* info); |
96 void PopulateDeoptimizationData(Handle<Code> code); | 94 void PopulateDeoptimizationData(Handle<Code> code); |
97 | 95 |
98 class StateField : public BitField<State, 0, 8> { }; | 96 class StateField : public BitField<State, 0, 8> { }; |
99 class PcField : public BitField<unsigned, 8, 32-8> { }; | 97 class PcField : public BitField<unsigned, 8, 32-8> { }; |
100 | 98 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 : NestedStatement(codegen) { | 266 : NestedStatement(codegen) { |
269 } | 267 } |
270 virtual ~WithOrCatch() {} | 268 virtual ~WithOrCatch() {} |
271 | 269 |
272 virtual NestedStatement* Exit(int* stack_depth, int* context_length) { | 270 virtual NestedStatement* Exit(int* stack_depth, int* context_length) { |
273 ++(*context_length); | 271 ++(*context_length); |
274 return previous_; | 272 return previous_; |
275 } | 273 } |
276 }; | 274 }; |
277 | 275 |
278 // The forward bailout stack keeps track of the expressions that can | |
279 // bail out to just before the control flow is split in a child | |
280 // node. The stack elements are linked together through the parent | |
281 // link when visiting expressions in test contexts after requesting | |
282 // bailout in child forwarding. | |
283 class ForwardBailoutStack BASE_EMBEDDED { | |
284 public: | |
285 ForwardBailoutStack(Expression* expr, ForwardBailoutStack* parent) | |
286 : expr_(expr), parent_(parent) { } | |
287 | |
288 Expression* expr() const { return expr_; } | |
289 ForwardBailoutStack* parent() const { return parent_; } | |
290 | |
291 private: | |
292 Expression* const expr_; | |
293 ForwardBailoutStack* const parent_; | |
294 }; | |
295 | |
296 // Type of a member function that generates inline code for a native function. | 276 // Type of a member function that generates inline code for a native function. |
297 typedef void (FullCodeGenerator::*InlineFunctionGenerator) | 277 typedef void (FullCodeGenerator::*InlineFunctionGenerator)(CallRuntime* expr); |
298 (ZoneList<Expression*>*); | |
299 | 278 |
300 static const InlineFunctionGenerator kInlineFunctionGenerators[]; | 279 static const InlineFunctionGenerator kInlineFunctionGenerators[]; |
301 | 280 |
302 // A platform-specific utility to overwrite the accumulator register | 281 // A platform-specific utility to overwrite the accumulator register |
303 // with a GC-safe value. | 282 // with a GC-safe value. |
304 void ClearAccumulator(); | 283 void ClearAccumulator(); |
305 | 284 |
306 // Determine whether or not to inline the smi case for the given | 285 // Determine whether or not to inline the smi case for the given |
307 // operation. | 286 // operation. |
308 bool ShouldInlineSmiCase(Token::Value op); | 287 bool ShouldInlineSmiCase(Token::Value op); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 // An operand used to read/write a stack-allocated (PARAMETER or LOCAL) | 328 // An operand used to read/write a stack-allocated (PARAMETER or LOCAL) |
350 // variable. Writing does not need the write barrier. | 329 // variable. Writing does not need the write barrier. |
351 MemOperand StackOperand(Variable* var); | 330 MemOperand StackOperand(Variable* var); |
352 | 331 |
353 // An operand used to read/write a known (PARAMETER, LOCAL, or CONTEXT) | 332 // An operand used to read/write a known (PARAMETER, LOCAL, or CONTEXT) |
354 // variable. May emit code to traverse the context chain, loading the | 333 // variable. May emit code to traverse the context chain, loading the |
355 // found context into the scratch register. Writing to this operand will | 334 // found context into the scratch register. Writing to this operand will |
356 // need the write barrier if location is CONTEXT. | 335 // need the write barrier if location is CONTEXT. |
357 MemOperand VarOperand(Variable* var, Register scratch); | 336 MemOperand VarOperand(Variable* var, Register scratch); |
358 | 337 |
359 // Forward the bailout responsibility for the given expression to | |
360 // the next child visited (which must be in a test context). | |
361 void ForwardBailoutToChild(Expression* expr); | |
362 | |
363 void VisitForEffect(Expression* expr) { | 338 void VisitForEffect(Expression* expr) { |
364 EffectContext context(this); | 339 EffectContext context(this); |
365 VisitInCurrentContext(expr); | 340 Visit(expr); |
| 341 PrepareForBailout(expr, NO_REGISTERS); |
366 } | 342 } |
367 | 343 |
368 void VisitForAccumulatorValue(Expression* expr) { | 344 void VisitForAccumulatorValue(Expression* expr) { |
369 AccumulatorValueContext context(this); | 345 AccumulatorValueContext context(this); |
370 VisitInCurrentContext(expr); | 346 Visit(expr); |
| 347 PrepareForBailout(expr, TOS_REG); |
371 } | 348 } |
372 | 349 |
373 void VisitForStackValue(Expression* expr) { | 350 void VisitForStackValue(Expression* expr) { |
374 StackValueContext context(this); | 351 StackValueContext context(this); |
375 VisitInCurrentContext(expr); | 352 Visit(expr); |
| 353 PrepareForBailout(expr, NO_REGISTERS); |
376 } | 354 } |
377 | 355 |
378 void VisitForControl(Expression* expr, | 356 void VisitForControl(Expression* expr, |
379 Label* if_true, | 357 Label* if_true, |
380 Label* if_false, | 358 Label* if_false, |
381 Label* fall_through) { | 359 Label* fall_through) { |
382 TestContext context(this, expr, if_true, if_false, fall_through); | 360 TestContext context(this, expr, if_true, if_false, fall_through); |
383 VisitInCurrentContext(expr); | 361 Visit(expr); |
| 362 // For test contexts, we prepare for bailout before branching, not at |
| 363 // the end of the entire expression. This happens as part of visiting |
| 364 // the expression. |
384 } | 365 } |
385 | 366 |
| 367 void VisitInDuplicateContext(Expression* expr); |
| 368 |
386 void VisitDeclarations(ZoneList<Declaration*>* declarations); | 369 void VisitDeclarations(ZoneList<Declaration*>* declarations); |
387 void DeclareGlobals(Handle<FixedArray> pairs); | 370 void DeclareGlobals(Handle<FixedArray> pairs); |
388 int DeclareGlobalsFlags(); | 371 int DeclareGlobalsFlags(); |
389 | 372 |
390 // Try to perform a comparison as a fast inlined literal compare if | 373 // Try to perform a comparison as a fast inlined literal compare if |
391 // the operands allow it. Returns true if the compare operations | 374 // the operands allow it. Returns true if the compare operations |
392 // has been matched and all code generated; false otherwise. | 375 // has been matched and all code generated; false otherwise. |
393 bool TryLiteralCompare(CompareOperation* compare); | 376 bool TryLiteralCompare(CompareOperation* compare); |
394 | 377 |
395 // Platform-specific code for comparing the type of a value with | 378 // Platform-specific code for comparing the type of a value with |
396 // a given literal string. | 379 // a given literal string. |
397 void EmitLiteralCompareTypeof(Expression* expr, Handle<String> check); | 380 void EmitLiteralCompareTypeof(Expression* expr, |
| 381 Expression* sub_expr, |
| 382 Handle<String> check); |
398 | 383 |
399 // Platform-specific code for equality comparison with a nil-like value. | 384 // Platform-specific code for equality comparison with a nil-like value. |
400 void EmitLiteralCompareNil(CompareOperation* expr, | 385 void EmitLiteralCompareNil(CompareOperation* expr, |
401 Expression* sub_expr, | 386 Expression* sub_expr, |
402 NilValue nil); | 387 NilValue nil); |
403 | 388 |
404 // Bailout support. | 389 // Bailout support. |
405 void PrepareForBailout(Expression* node, State state); | 390 void PrepareForBailout(Expression* node, State state); |
406 void PrepareForBailoutForId(int id, State state); | 391 void PrepareForBailoutForId(int id, State state); |
407 | 392 |
408 // Record a call's return site offset, used to rebuild the frame if the | 393 // Record a call's return site offset, used to rebuild the frame if the |
409 // called function was inlined at the site. | 394 // called function was inlined at the site. |
410 void RecordJSReturnSite(Call* call); | 395 void RecordJSReturnSite(Call* call); |
411 | 396 |
412 // Prepare for bailout before a test (or compare) and branch. If | 397 // Prepare for bailout before a test (or compare) and branch. If |
413 // should_normalize, then the following comparison will not handle the | 398 // should_normalize, then the following comparison will not handle the |
414 // canonical JS true value so we will insert a (dead) test against true at | 399 // canonical JS true value so we will insert a (dead) test against true at |
415 // the actual bailout target from the optimized code. If not | 400 // the actual bailout target from the optimized code. If not |
416 // should_normalize, the true and false labels are ignored. | 401 // should_normalize, the true and false labels are ignored. |
417 void PrepareForBailoutBeforeSplit(State state, | 402 void PrepareForBailoutBeforeSplit(Expression* expr, |
418 bool should_normalize, | 403 bool should_normalize, |
419 Label* if_true, | 404 Label* if_true, |
420 Label* if_false); | 405 Label* if_false); |
421 | 406 |
422 // Platform-specific code for a variable, constant, or function | 407 // Platform-specific code for a variable, constant, or function |
423 // declaration. Functions have an initial value. | 408 // declaration. Functions have an initial value. |
424 void EmitDeclaration(VariableProxy* proxy, | 409 void EmitDeclaration(VariableProxy* proxy, |
425 VariableMode mode, | 410 VariableMode mode, |
426 FunctionLiteral* function, | 411 FunctionLiteral* function, |
427 int* global_count); | 412 int* global_count); |
(...skipping 14 matching lines...) Expand all Loading... |
442 void EmitCallWithStub(Call* expr, CallFunctionFlags flags); | 427 void EmitCallWithStub(Call* expr, CallFunctionFlags flags); |
443 void EmitCallWithIC(Call* expr, Handle<Object> name, RelocInfo::Mode mode); | 428 void EmitCallWithIC(Call* expr, Handle<Object> name, RelocInfo::Mode mode); |
444 void EmitKeyedCallWithIC(Call* expr, Expression* key); | 429 void EmitKeyedCallWithIC(Call* expr, Expression* key); |
445 | 430 |
446 // Platform-specific code for inline runtime calls. | 431 // Platform-specific code for inline runtime calls. |
447 InlineFunctionGenerator FindInlineFunctionGenerator(Runtime::FunctionId id); | 432 InlineFunctionGenerator FindInlineFunctionGenerator(Runtime::FunctionId id); |
448 | 433 |
449 void EmitInlineRuntimeCall(CallRuntime* expr); | 434 void EmitInlineRuntimeCall(CallRuntime* expr); |
450 | 435 |
451 #define EMIT_INLINE_RUNTIME_CALL(name, x, y) \ | 436 #define EMIT_INLINE_RUNTIME_CALL(name, x, y) \ |
452 void Emit##name(ZoneList<Expression*>* arguments); | 437 void Emit##name(CallRuntime* expr); |
453 INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) | 438 INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) |
454 INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) | 439 INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) |
455 #undef EMIT_INLINE_RUNTIME_CALL | 440 #undef EMIT_INLINE_RUNTIME_CALL |
456 | 441 |
457 // Platform-specific code for loading variables. | 442 // Platform-specific code for loading variables. |
458 void EmitLoadGlobalCheckExtensions(Variable* var, | 443 void EmitLoadGlobalCheckExtensions(Variable* var, |
459 TypeofState typeof_state, | 444 TypeofState typeof_state, |
460 Label* slow); | 445 Label* slow); |
461 MemOperand ContextSlotOperandCheckExtensions(Variable* var, Label* slow); | 446 MemOperand ContextSlotOperandCheckExtensions(Variable* var, Label* slow); |
462 void EmitDynamicLookupFastCase(Variable* var, | 447 void EmitDynamicLookupFastCase(Variable* var, |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 // AST node visit functions. | 554 // AST node visit functions. |
570 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); | 555 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); |
571 AST_NODE_LIST(DECLARE_VISIT) | 556 AST_NODE_LIST(DECLARE_VISIT) |
572 #undef DECLARE_VISIT | 557 #undef DECLARE_VISIT |
573 | 558 |
574 void EmitUnaryOperation(UnaryOperation* expr, const char* comment); | 559 void EmitUnaryOperation(UnaryOperation* expr, const char* comment); |
575 | 560 |
576 void VisitComma(BinaryOperation* expr); | 561 void VisitComma(BinaryOperation* expr); |
577 void VisitLogicalExpression(BinaryOperation* expr); | 562 void VisitLogicalExpression(BinaryOperation* expr); |
578 void VisitArithmeticExpression(BinaryOperation* expr); | 563 void VisitArithmeticExpression(BinaryOperation* expr); |
579 void VisitInCurrentContext(Expression* expr); | |
580 | 564 |
581 void VisitForTypeofValue(Expression* expr); | 565 void VisitForTypeofValue(Expression* expr); |
582 | 566 |
583 struct BailoutEntry { | 567 struct BailoutEntry { |
584 unsigned id; | 568 unsigned id; |
585 unsigned pc_and_state; | 569 unsigned pc_and_state; |
586 }; | 570 }; |
587 | 571 |
588 | 572 |
589 class ExpressionContext BASE_EMBEDDED { | 573 class ExpressionContext BASE_EMBEDDED { |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
764 | 748 |
765 MacroAssembler* masm_; | 749 MacroAssembler* masm_; |
766 CompilationInfo* info_; | 750 CompilationInfo* info_; |
767 Scope* scope_; | 751 Scope* scope_; |
768 Label return_label_; | 752 Label return_label_; |
769 NestedStatement* nesting_stack_; | 753 NestedStatement* nesting_stack_; |
770 int loop_depth_; | 754 int loop_depth_; |
771 const ExpressionContext* context_; | 755 const ExpressionContext* context_; |
772 ZoneList<BailoutEntry> bailout_entries_; | 756 ZoneList<BailoutEntry> bailout_entries_; |
773 ZoneList<BailoutEntry> stack_checks_; | 757 ZoneList<BailoutEntry> stack_checks_; |
774 ForwardBailoutStack* forward_bailout_stack_; | |
775 ForwardBailoutStack* forward_bailout_pending_; | |
776 | 758 |
777 friend class NestedStatement; | 759 friend class NestedStatement; |
778 | 760 |
779 DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator); | 761 DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator); |
780 }; | 762 }; |
781 | 763 |
782 | 764 |
783 } } // namespace v8::internal | 765 } } // namespace v8::internal |
784 | 766 |
785 #endif // V8_FULL_CODEGEN_H_ | 767 #endif // V8_FULL_CODEGEN_H_ |
OLD | NEW |