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 2462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2473 header->SetInitialEnvironment(entry_env); | 2473 header->SetInitialEnvironment(entry_env); |
2474 header->AttachLoopInformation(); | 2474 header->AttachLoopInformation(); |
2475 return header; | 2475 return header; |
2476 } | 2476 } |
2477 | 2477 |
2478 | 2478 |
2479 void HGraphBuilder::VisitBlock(Block* stmt) { | 2479 void HGraphBuilder::VisitBlock(Block* stmt) { |
2480 ASSERT(!HasStackOverflow()); | 2480 ASSERT(!HasStackOverflow()); |
2481 ASSERT(current_block() != NULL); | 2481 ASSERT(current_block() != NULL); |
2482 ASSERT(current_block()->HasPredecessor()); | 2482 ASSERT(current_block()->HasPredecessor()); |
| 2483 if (stmt->block_scope() != NULL) { |
| 2484 return Bailout("ScopedBlock"); |
| 2485 } |
2483 BreakAndContinueInfo break_info(stmt); | 2486 BreakAndContinueInfo break_info(stmt); |
2484 { BreakAndContinueScope push(&break_info, this); | 2487 { BreakAndContinueScope push(&break_info, this); |
2485 CHECK_BAILOUT(VisitStatements(stmt->statements())); | 2488 CHECK_BAILOUT(VisitStatements(stmt->statements())); |
2486 } | 2489 } |
2487 HBasicBlock* break_block = break_info.break_block(); | 2490 HBasicBlock* break_block = break_info.break_block(); |
2488 if (break_block != NULL) { | 2491 if (break_block != NULL) { |
2489 if (current_block() != NULL) current_block()->Goto(break_block); | 2492 if (current_block() != NULL) current_block()->Goto(break_block); |
2490 break_block->SetJoinId(stmt->ExitId()); | 2493 break_block->SetJoinId(stmt->ExitId()); |
2491 set_current_block(break_block); | 2494 set_current_block(break_block); |
2492 } | 2495 } |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2624 ASSERT(context->IsValue()); | 2627 ASSERT(context->IsValue()); |
2625 CHECK_ALIVE(VisitForValue(stmt->expression())); | 2628 CHECK_ALIVE(VisitForValue(stmt->expression())); |
2626 HValue* return_value = environment()->Pop(); | 2629 HValue* return_value = environment()->Pop(); |
2627 current_block()->AddLeaveInlined(return_value, function_return()); | 2630 current_block()->AddLeaveInlined(return_value, function_return()); |
2628 } | 2631 } |
2629 set_current_block(NULL); | 2632 set_current_block(NULL); |
2630 } | 2633 } |
2631 } | 2634 } |
2632 | 2635 |
2633 | 2636 |
2634 void HGraphBuilder::VisitEnterWithContextStatement( | 2637 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
2635 EnterWithContextStatement* stmt) { | |
2636 ASSERT(!HasStackOverflow()); | 2638 ASSERT(!HasStackOverflow()); |
2637 ASSERT(current_block() != NULL); | 2639 ASSERT(current_block() != NULL); |
2638 ASSERT(current_block()->HasPredecessor()); | 2640 ASSERT(current_block()->HasPredecessor()); |
2639 return Bailout("EnterWithContextStatement"); | 2641 return Bailout("WithStatement"); |
2640 } | 2642 } |
2641 | 2643 |
2642 | 2644 |
2643 void HGraphBuilder::VisitExitContextStatement(ExitContextStatement* stmt) { | 2645 void HGraphBuilder::VisitExitContextStatement(ExitContextStatement* stmt) { |
2644 ASSERT(!HasStackOverflow()); | 2646 ASSERT(!HasStackOverflow()); |
2645 ASSERT(current_block() != NULL); | 2647 ASSERT(current_block() != NULL); |
2646 ASSERT(current_block()->HasPredecessor()); | 2648 ASSERT(current_block()->HasPredecessor()); |
2647 return Bailout("ExitContextStatement"); | 2649 return Bailout("ExitContextStatement"); |
2648 } | 2650 } |
2649 | 2651 |
(...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3933 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map)); | 3935 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map)); |
3934 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); | 3936 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); |
3935 bool fast_double_elements = map->has_fast_double_elements(); | 3937 bool fast_double_elements = map->has_fast_double_elements(); |
3936 if (is_store && map->has_fast_elements()) { | 3938 if (is_store && map->has_fast_elements()) { |
3937 AddInstruction(new(zone()) HCheckMap( | 3939 AddInstruction(new(zone()) HCheckMap( |
3938 elements, isolate()->factory()->fixed_array_map())); | 3940 elements, isolate()->factory()->fixed_array_map())); |
3939 } | 3941 } |
3940 HInstruction* length = NULL; | 3942 HInstruction* length = NULL; |
3941 HInstruction* checked_key = NULL; | 3943 HInstruction* checked_key = NULL; |
3942 if (map->has_external_array_elements()) { | 3944 if (map->has_external_array_elements()) { |
3943 length = AddInstruction(new(zone()) HExternalArrayLength(elements)); | 3945 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
3944 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3946 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3945 HLoadExternalArrayPointer* external_elements = | 3947 HLoadExternalArrayPointer* external_elements = |
3946 new(zone()) HLoadExternalArrayPointer(elements); | 3948 new(zone()) HLoadExternalArrayPointer(elements); |
3947 AddInstruction(external_elements); | 3949 AddInstruction(external_elements); |
3948 return BuildExternalArrayElementAccess(external_elements, checked_key, | 3950 return BuildExternalArrayElementAccess(external_elements, checked_key, |
3949 val, map->elements_kind(), is_store); | 3951 val, map->elements_kind(), is_store); |
3950 } | 3952 } |
3951 ASSERT(map->has_fast_elements() || fast_double_elements); | 3953 ASSERT(map->has_fast_elements() || fast_double_elements); |
3952 if (map->instance_type() == JS_ARRAY_TYPE) { | 3954 if (map->instance_type() == JS_ARRAY_TYPE) { |
3953 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck)); | 3955 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck)); |
3954 } else { | 3956 } else { |
3955 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 3957 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
3956 } | 3958 } |
3957 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3959 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3958 if (is_store) { | 3960 if (is_store) { |
3959 if (fast_double_elements) { | 3961 if (fast_double_elements) { |
3960 return new(zone()) HStoreKeyedFastDoubleElement(elements, | 3962 return new(zone()) HStoreKeyedFastDoubleElement(elements, |
3961 checked_key, | 3963 checked_key, |
3962 val); | 3964 val); |
3963 } else { | 3965 } else { |
3964 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); | 3966 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); |
3965 } | 3967 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4017 for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS; | 4019 for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS; |
4018 elements_kind <= JSObject::LAST_ELEMENTS_KIND; | 4020 elements_kind <= JSObject::LAST_ELEMENTS_KIND; |
4019 elements_kind = JSObject::ElementsKind(elements_kind + 1)) { | 4021 elements_kind = JSObject::ElementsKind(elements_kind + 1)) { |
4020 // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we | 4022 // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we |
4021 // need to add some code that's executed for all external array cases. | 4023 // need to add some code that's executed for all external array cases. |
4022 STATIC_ASSERT(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == | 4024 STATIC_ASSERT(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == |
4023 JSObject::LAST_ELEMENTS_KIND); | 4025 JSObject::LAST_ELEMENTS_KIND); |
4024 if (elements_kind == JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND | 4026 if (elements_kind == JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND |
4025 && todo_external_array) { | 4027 && todo_external_array) { |
4026 HInstruction* length = | 4028 HInstruction* length = |
4027 AddInstruction(new(zone()) HExternalArrayLength(elements)); | 4029 AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
4028 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4030 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
4029 external_elements = new(zone()) HLoadExternalArrayPointer(elements); | 4031 external_elements = new(zone()) HLoadExternalArrayPointer(elements); |
4030 AddInstruction(external_elements); | 4032 AddInstruction(external_elements); |
4031 } | 4033 } |
4032 if (type_todo[elements_kind]) { | 4034 if (type_todo[elements_kind]) { |
4033 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 4035 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
4034 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 4036 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
4035 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( | 4037 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( |
4036 elements_kind_instr, elements_kind, Token::EQ_STRICT); | 4038 elements_kind_instr, elements_kind, Token::EQ_STRICT); |
4037 elements_kind_branch->SetSuccessorAt(0, if_true); | 4039 elements_kind_branch->SetSuccessorAt(0, if_true); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4081 } | 4083 } |
4082 Push(access); | 4084 Push(access); |
4083 } | 4085 } |
4084 *has_side_effects |= access->HasSideEffects(); | 4086 *has_side_effects |= access->HasSideEffects(); |
4085 if (position != -1) { | 4087 if (position != -1) { |
4086 access->set_position(position); | 4088 access->set_position(position); |
4087 } | 4089 } |
4088 if_jsarray->Goto(join); | 4090 if_jsarray->Goto(join); |
4089 | 4091 |
4090 set_current_block(if_fastobject); | 4092 set_current_block(if_fastobject); |
4091 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 4093 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
4092 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4094 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
4093 if (is_store) { | 4095 if (is_store) { |
4094 if (fast_double_elements) { | 4096 if (fast_double_elements) { |
4095 access = AddInstruction( | 4097 access = AddInstruction( |
4096 new(zone()) HStoreKeyedFastDoubleElement(elements, | 4098 new(zone()) HStoreKeyedFastDoubleElement(elements, |
4097 checked_key, | 4099 checked_key, |
4098 val)); | 4100 val)); |
4099 } else { | 4101 } else { |
4100 access = AddInstruction( | 4102 access = AddInstruction( |
4101 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); | 4103 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); |
(...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4755 } | 4757 } |
4756 return false; | 4758 return false; |
4757 } | 4759 } |
4758 | 4760 |
4759 | 4761 |
4760 bool HGraphBuilder::TryCallApply(Call* expr) { | 4762 bool HGraphBuilder::TryCallApply(Call* expr) { |
4761 Expression* callee = expr->expression(); | 4763 Expression* callee = expr->expression(); |
4762 Property* prop = callee->AsProperty(); | 4764 Property* prop = callee->AsProperty(); |
4763 ASSERT(prop != NULL); | 4765 ASSERT(prop != NULL); |
4764 | 4766 |
| 4767 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { |
| 4768 return false; |
| 4769 } |
| 4770 Handle<Map> function_map = expr->GetReceiverTypes()->first(); |
| 4771 if (function_map->instance_type() != JS_FUNCTION_TYPE || |
| 4772 !expr->target()->shared()->HasBuiltinFunctionId() || |
| 4773 expr->target()->shared()->builtin_function_id() != kFunctionApply) { |
| 4774 return false; |
| 4775 } |
| 4776 |
4765 if (info()->scope()->arguments() == NULL) return false; | 4777 if (info()->scope()->arguments() == NULL) return false; |
4766 | 4778 |
4767 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | |
4768 if (!name->IsEqualTo(CStrVector("apply"))) return false; | |
4769 | |
4770 ZoneList<Expression*>* args = expr->arguments(); | 4779 ZoneList<Expression*>* args = expr->arguments(); |
4771 if (args->length() != 2) return false; | 4780 if (args->length() != 2) return false; |
4772 | 4781 |
4773 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 4782 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
4774 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 4783 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
4775 HValue* arg_two_value = environment()->Lookup(arg_two->var()); | 4784 HValue* arg_two_value = environment()->Lookup(arg_two->var()); |
4776 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 4785 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
4777 | 4786 |
4778 if (!expr->IsMonomorphic() || | |
4779 expr->check_type() != RECEIVER_MAP_CHECK) return false; | |
4780 | |
4781 // Our implementation of arguments (based on this stack frame or an | 4787 // Our implementation of arguments (based on this stack frame or an |
4782 // adapter below it) does not work for inlined functions. | 4788 // adapter below it) does not work for inlined functions. |
4783 if (function_state()->outer() != NULL) { | 4789 if (function_state()->outer() != NULL) { |
4784 Bailout("Function.prototype.apply optimization in inlined function"); | 4790 Bailout("Function.prototype.apply optimization in inlined function"); |
4785 return true; | 4791 return true; |
4786 } | 4792 } |
4787 | 4793 |
4788 // Found pattern f.apply(receiver, arguments). | 4794 // Found pattern f.apply(receiver, arguments). |
4789 VisitForValue(prop->obj()); | 4795 VisitForValue(prop->obj()); |
4790 if (HasStackOverflow() || current_block() == NULL) return true; | 4796 if (HasStackOverflow() || current_block() == NULL) return true; |
4791 HValue* function = Pop(); | 4797 HValue* function = Pop(); |
4792 VisitForValue(args->at(0)); | 4798 VisitForValue(args->at(0)); |
4793 if (HasStackOverflow() || current_block() == NULL) return true; | 4799 if (HasStackOverflow() || current_block() == NULL) return true; |
4794 HValue* receiver = Pop(); | 4800 HValue* receiver = Pop(); |
4795 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); | 4801 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
4796 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); | 4802 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
4797 AddCheckConstantFunction(expr, | 4803 AddCheckConstantFunction(expr, function, function_map, true); |
4798 function, | |
4799 expr->GetReceiverTypes()->first(), | |
4800 true); | |
4801 HInstruction* result = | 4804 HInstruction* result = |
4802 new(zone()) HApplyArguments(function, receiver, length, elements); | 4805 new(zone()) HApplyArguments(function, receiver, length, elements); |
4803 result->set_position(expr->position()); | 4806 result->set_position(expr->position()); |
4804 ast_context()->ReturnInstruction(result, expr->id()); | 4807 ast_context()->ReturnInstruction(result, expr->id()); |
4805 return true; | 4808 return true; |
4806 } | 4809 } |
4807 | 4810 |
4808 | 4811 |
4809 void HGraphBuilder::VisitCall(Call* expr) { | 4812 void HGraphBuilder::VisitCall(Call* expr) { |
4810 ASSERT(!HasStackOverflow()); | 4813 ASSERT(!HasStackOverflow()); |
(...skipping 1935 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6746 } | 6749 } |
6747 } | 6750 } |
6748 | 6751 |
6749 #ifdef DEBUG | 6752 #ifdef DEBUG |
6750 if (graph_ != NULL) graph_->Verify(); | 6753 if (graph_ != NULL) graph_->Verify(); |
6751 if (allocator_ != NULL) allocator_->Verify(); | 6754 if (allocator_ != NULL) allocator_->Verify(); |
6752 #endif | 6755 #endif |
6753 } | 6756 } |
6754 | 6757 |
6755 } } // namespace v8::internal | 6758 } } // namespace v8::internal |
OLD | NEW |