OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 1634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1645 right_side.Unuse(); | 1645 right_side.Unuse(); |
1646 left_side.Unuse(); | 1646 left_side.Unuse(); |
1647 dest->Split(cc); | 1647 dest->Split(cc); |
1648 } | 1648 } |
1649 } | 1649 } |
1650 } | 1650 } |
1651 | 1651 |
1652 | 1652 |
1653 class CallFunctionStub: public CodeStub { | 1653 class CallFunctionStub: public CodeStub { |
1654 public: | 1654 public: |
1655 explicit CallFunctionStub(int argc) : argc_(argc) { } | 1655 CallFunctionStub(int argc, InlineCacheInLoop in_loop) |
| 1656 : argc_(argc), in_loop_(in_loop) { } |
1656 | 1657 |
1657 void Generate(MacroAssembler* masm); | 1658 void Generate(MacroAssembler* masm); |
1658 | 1659 |
1659 private: | 1660 private: |
1660 int argc_; | 1661 int argc_; |
| 1662 InlineCacheInLoop in_loop_; |
1661 | 1663 |
1662 #ifdef DEBUG | 1664 #ifdef DEBUG |
1663 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); } | 1665 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); } |
1664 #endif | 1666 #endif |
1665 | 1667 |
1666 Major MajorKey() { return CallFunction; } | 1668 Major MajorKey() { return CallFunction; } |
1667 int MinorKey() { return argc_; } | 1669 int MinorKey() { return argc_; } |
| 1670 InlineCacheInLoop InLoop() { return in_loop_; } |
1668 }; | 1671 }; |
1669 | 1672 |
1670 | 1673 |
1671 // Call the function just below TOS on the stack with the given | 1674 // Call the function just below TOS on the stack with the given |
1672 // arguments. The receiver is the TOS. | 1675 // arguments. The receiver is the TOS. |
1673 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, | 1676 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, |
1674 int position) { | 1677 int position) { |
1675 // Push the arguments ("left-to-right") on the stack. | 1678 // Push the arguments ("left-to-right") on the stack. |
1676 int arg_count = args->length(); | 1679 int arg_count = args->length(); |
1677 for (int i = 0; i < arg_count; i++) { | 1680 for (int i = 0; i < arg_count; i++) { |
1678 Load(args->at(i)); | 1681 Load(args->at(i)); |
1679 } | 1682 } |
1680 | 1683 |
1681 // Record the position for debugging purposes. | 1684 // Record the position for debugging purposes. |
1682 CodeForSourcePosition(position); | 1685 CodeForSourcePosition(position); |
1683 | 1686 |
1684 // Use the shared code stub to call the function. | 1687 // Use the shared code stub to call the function. |
1685 CallFunctionStub call_function(arg_count); | 1688 InlineCacheInLoop in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
| 1689 CallFunctionStub call_function(arg_count, in_loop); |
1686 Result answer = frame_->CallStub(&call_function, arg_count + 1); | 1690 Result answer = frame_->CallStub(&call_function, arg_count + 1); |
1687 // Restore context and replace function on the stack with the | 1691 // Restore context and replace function on the stack with the |
1688 // result of the stub invocation. | 1692 // result of the stub invocation. |
1689 frame_->RestoreContextRegister(); | 1693 frame_->RestoreContextRegister(); |
1690 frame_->SetElementAt(0, &answer); | 1694 frame_->SetElementAt(0, &answer); |
1691 } | 1695 } |
1692 | 1696 |
1693 | 1697 |
1694 class DeferredStackCheck: public DeferredCode { | 1698 class DeferredStackCheck: public DeferredCode { |
1695 public: | 1699 public: |
(...skipping 2513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4209 frame_->SetElementAt(arg_count + 1, &scratch); | 4213 frame_->SetElementAt(arg_count + 1, &scratch); |
4210 | 4214 |
4211 // We can reuse the result register now. | 4215 // We can reuse the result register now. |
4212 frame_->Spill(result.reg()); | 4216 frame_->Spill(result.reg()); |
4213 __ mov(result.reg(), | 4217 __ mov(result.reg(), |
4214 FieldOperand(result.reg(), FixedArray::kHeaderSize + kPointerSize)); | 4218 FieldOperand(result.reg(), FixedArray::kHeaderSize + kPointerSize)); |
4215 frame_->SetElementAt(arg_count, &result); | 4219 frame_->SetElementAt(arg_count, &result); |
4216 | 4220 |
4217 // Call the function. | 4221 // Call the function. |
4218 CodeForSourcePosition(node->position()); | 4222 CodeForSourcePosition(node->position()); |
4219 CallFunctionStub call_function(arg_count); | 4223 InlineCacheInLoop in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
| 4224 CallFunctionStub call_function(arg_count, in_loop); |
4220 result = frame_->CallStub(&call_function, arg_count + 1); | 4225 result = frame_->CallStub(&call_function, arg_count + 1); |
4221 | 4226 |
4222 // Restore the context and overwrite the function on the stack with | 4227 // Restore the context and overwrite the function on the stack with |
4223 // the result. | 4228 // the result. |
4224 frame_->RestoreContextRegister(); | 4229 frame_->RestoreContextRegister(); |
4225 frame_->SetElementAt(0, &result); | 4230 frame_->SetElementAt(0, &result); |
4226 } | 4231 } |
4227 | 4232 |
4228 | 4233 |
4229 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { | 4234 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4573 frame_->Push(&temp); | 4578 frame_->Push(&temp); |
4574 } | 4579 } |
4575 | 4580 |
4576 // Push the arguments ("left-to-right"). | 4581 // Push the arguments ("left-to-right"). |
4577 int arg_count = args->length(); | 4582 int arg_count = args->length(); |
4578 for (int i = 0; i < arg_count; i++) { | 4583 for (int i = 0; i < arg_count; i++) { |
4579 Load(args->at(i)); | 4584 Load(args->at(i)); |
4580 } | 4585 } |
4581 | 4586 |
4582 if (function == NULL) { | 4587 if (function == NULL) { |
4583 // Call the JS runtime function. Pass 0 as the loop nesting depth | 4588 // Call the JS runtime function. |
4584 // because we do not handle runtime calls specially in loops. | 4589 Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET, |
4585 Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count, 0); | 4590 arg_count, |
| 4591 loop_nesting_); |
4586 frame_->RestoreContextRegister(); | 4592 frame_->RestoreContextRegister(); |
4587 frame_->SetElementAt(0, &answer); | 4593 frame_->SetElementAt(0, &answer); |
4588 } else { | 4594 } else { |
4589 // Call the C runtime function. | 4595 // Call the C runtime function. |
4590 Result answer = frame_->CallRuntime(function, arg_count); | 4596 Result answer = frame_->CallRuntime(function, arg_count); |
4591 frame_->Push(&answer); | 4597 frame_->Push(&answer); |
4592 } | 4598 } |
4593 } | 4599 } |
4594 | 4600 |
4595 | 4601 |
(...skipping 791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5387 // TODO(1241834): Make sure that it is safe to ignore the | 5393 // TODO(1241834): Make sure that it is safe to ignore the |
5388 // distinction between expressions in a typeof and not in a | 5394 // distinction between expressions in a typeof and not in a |
5389 // typeof. If there is a chance that reference errors can be | 5395 // typeof. If there is a chance that reference errors can be |
5390 // thrown below, we must distinguish between the two kinds of | 5396 // thrown below, we must distinguish between the two kinds of |
5391 // loads (typeof expression loads must not throw a reference | 5397 // loads (typeof expression loads must not throw a reference |
5392 // error). | 5398 // error). |
5393 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 5399 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
5394 bool is_global = var != NULL; | 5400 bool is_global = var != NULL; |
5395 ASSERT(!is_global || var->is_global()); | 5401 ASSERT(!is_global || var->is_global()); |
5396 | 5402 |
5397 if (is_global || cgen_->scope()->is_global_scope()) { | 5403 // Do not inline the inobject property case for loads from the global |
5398 // Do not inline the inobject property case for loads from the | 5404 // object. Also do not inline for unoptimized code. This saves time |
5399 // global object or loads in toplevel code. | 5405 // in the code generator. Unoptimized code is toplevel code or code |
| 5406 // that is not in a loop. |
| 5407 if (is_global || |
| 5408 cgen_->scope()->is_global_scope() || |
| 5409 cgen_->loop_nesting() == 0) { |
5400 Comment cmnt(masm, "[ Load from named Property"); | 5410 Comment cmnt(masm, "[ Load from named Property"); |
5401 cgen_->frame()->Push(GetName()); | 5411 cgen_->frame()->Push(GetName()); |
5402 | 5412 |
5403 RelocInfo::Mode mode = is_global | 5413 RelocInfo::Mode mode = is_global |
5404 ? RelocInfo::CODE_TARGET_CONTEXT | 5414 ? RelocInfo::CODE_TARGET_CONTEXT |
5405 : RelocInfo::CODE_TARGET; | 5415 : RelocInfo::CODE_TARGET; |
5406 Result answer = cgen_->frame()->CallLoadIC(mode); | 5416 Result answer = cgen_->frame()->CallLoadIC(mode); |
5407 // A test eax instruction following the call signals that the | 5417 // A test eax instruction following the call signals that the |
5408 // inobject property case was inlined. Ensure that there is not | 5418 // inobject property case was inlined. Ensure that there is not |
5409 // a test eax instruction here. | 5419 // a test eax instruction here. |
(...skipping 1858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7268 | 7278 |
7269 // Slow-case: Go through the JavaScript implementation. | 7279 // Slow-case: Go through the JavaScript implementation. |
7270 __ bind(&slow); | 7280 __ bind(&slow); |
7271 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 7281 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
7272 } | 7282 } |
7273 | 7283 |
7274 | 7284 |
7275 #undef __ | 7285 #undef __ |
7276 | 7286 |
7277 } } // namespace v8::internal | 7287 } } // namespace v8::internal |
OLD | NEW |