| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 3147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3158 // from the end of the fixed part of the object. | 3158 // from the end of the fixed part of the object. |
| 3159 offset += type->instance_size(); | 3159 offset += type->instance_size(); |
| 3160 } else { | 3160 } else { |
| 3161 offset += FixedArray::kHeaderSize; | 3161 offset += FixedArray::kHeaderSize; |
| 3162 } | 3162 } |
| 3163 HStoreNamedField* instr = | 3163 HStoreNamedField* instr = |
| 3164 new HStoreNamedField(object, name, value, is_in_object, offset); | 3164 new HStoreNamedField(object, name, value, is_in_object, offset); |
| 3165 if (lookup->type() == MAP_TRANSITION) { | 3165 if (lookup->type() == MAP_TRANSITION) { |
| 3166 Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); | 3166 Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); |
| 3167 instr->set_transition(transition); | 3167 instr->set_transition(transition); |
| 3168 // TODO(fschneider): Record the new map type of the object in the IR to |
| 3169 // enable elimination of redundant checks after the transition store. |
| 3170 instr->SetFlag(HValue::kChangesMaps); |
| 3168 } | 3171 } |
| 3169 return instr; | 3172 return instr; |
| 3170 } | 3173 } |
| 3171 | 3174 |
| 3172 | 3175 |
| 3173 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, | 3176 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, |
| 3174 Handle<String> name, | 3177 Handle<String> name, |
| 3175 HValue* value) { | 3178 HValue* value) { |
| 3176 return new HStoreNamedGeneric(object, name, value); | 3179 return new HStoreNamedGeneric(object, name, value); |
| 3177 } | 3180 } |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3522 // different maps are identical. In that case we can avoid | 3525 // different maps are identical. In that case we can avoid |
| 3523 // repeatedly generating the same prototype map checks. | 3526 // repeatedly generating the same prototype map checks. |
| 3524 for (int i = 0; i < number_of_types; ++i) { | 3527 for (int i = 0; i < number_of_types; ++i) { |
| 3525 Handle<Map> map = types->at(i); | 3528 Handle<Map> map = types->at(i); |
| 3526 LookupResult lookup; | 3529 LookupResult lookup; |
| 3527 map->LookupInDescriptors(NULL, *name, &lookup); | 3530 map->LookupInDescriptors(NULL, *name, &lookup); |
| 3528 if (lookup.IsProperty() && lookup.type() == FIELD) { | 3531 if (lookup.IsProperty() && lookup.type() == FIELD) { |
| 3529 maps.Add(map); | 3532 maps.Add(map); |
| 3530 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | 3533 HSubgraph* subgraph = CreateBranchSubgraph(environment()); |
| 3531 SubgraphScope scope(this, subgraph); | 3534 SubgraphScope scope(this, subgraph); |
| 3532 HInstruction* instr = | 3535 HLoadNamedField* instr = |
| 3533 BuildLoadNamedField(object, expr, map, &lookup, false); | 3536 BuildLoadNamedField(object, expr, map, &lookup, false); |
| 3534 instr->set_position(expr->position()); | 3537 instr->set_position(expr->position()); |
| 3538 instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads. |
| 3535 PushAndAdd(instr); | 3539 PushAndAdd(instr); |
| 3536 subgraphs.Add(subgraph); | 3540 subgraphs.Add(subgraph); |
| 3537 } else { | 3541 } else { |
| 3538 needs_generic = true; | 3542 needs_generic = true; |
| 3539 } | 3543 } |
| 3540 } | 3544 } |
| 3541 | 3545 |
| 3542 // If none of the properties were named fields we generate a | 3546 // If none of the properties were named fields we generate a |
| 3543 // generic load. | 3547 // generic load. |
| 3544 if (maps.length() == 0) { | 3548 if (maps.length() == 0) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3563 | 3567 |
| 3564 HBasicBlock* new_exit_block = | 3568 HBasicBlock* new_exit_block = |
| 3565 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); | 3569 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); |
| 3566 subgraph()->set_exit_block(new_exit_block); | 3570 subgraph()->set_exit_block(new_exit_block); |
| 3567 } | 3571 } |
| 3568 | 3572 |
| 3569 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop()); | 3573 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop()); |
| 3570 } | 3574 } |
| 3571 | 3575 |
| 3572 | 3576 |
| 3573 HInstruction* HGraphBuilder::BuildLoadNamedField(HValue* object, | 3577 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
| 3574 Property* expr, | 3578 Property* expr, |
| 3575 Handle<Map> type, | 3579 Handle<Map> type, |
| 3576 LookupResult* lookup, | 3580 LookupResult* lookup, |
| 3577 bool smi_and_map_check) { | 3581 bool smi_and_map_check) { |
| 3578 if (smi_and_map_check) { | 3582 if (smi_and_map_check) { |
| 3579 AddInstruction(new HCheckNonSmi(object)); | 3583 AddInstruction(new HCheckNonSmi(object)); |
| 3580 AddInstruction(new HCheckMap(object, type)); | 3584 AddInstruction(new HCheckMap(object, type)); |
| 3581 } | 3585 } |
| 3582 | 3586 |
| 3583 int index = lookup->GetLocalFieldIndexFromMap(*type); | 3587 int index = lookup->GetLocalFieldIndexFromMap(*type); |
| 3584 if (index < 0) { | 3588 if (index < 0) { |
| 3585 // Negative property indices are in-object properties, indexed | 3589 // Negative property indices are in-object properties, indexed |
| 3586 // from the end of the fixed part of the object. | 3590 // from the end of the fixed part of the object. |
| 3587 int offset = (index * kPointerSize) + type->instance_size(); | 3591 int offset = (index * kPointerSize) + type->instance_size(); |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4086 // Try to inline calls like Math.* as operations in the calling function. | 4090 // Try to inline calls like Math.* as operations in the calling function. |
| 4087 if (!expr->target()->shared()->IsBuiltinMathFunction()) return false; | 4091 if (!expr->target()->shared()->IsBuiltinMathFunction()) return false; |
| 4088 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 4092 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
| 4089 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 4093 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 4090 switch (id) { | 4094 switch (id) { |
| 4091 case kMathRound: | 4095 case kMathRound: |
| 4092 case kMathFloor: | 4096 case kMathFloor: |
| 4093 case kMathAbs: | 4097 case kMathAbs: |
| 4094 case kMathSqrt: | 4098 case kMathSqrt: |
| 4095 case kMathLog: | 4099 case kMathLog: |
| 4100 case kMathSin: |
| 4101 case kMathCos: |
| 4096 if (argument_count == 2) { | 4102 if (argument_count == 2) { |
| 4097 HValue* argument = Pop(); | 4103 HValue* argument = Pop(); |
| 4098 Drop(1); // Receiver. | 4104 Drop(1); // Receiver. |
| 4099 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id); | 4105 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id); |
| 4100 op->set_position(expr->position()); | 4106 op->set_position(expr->position()); |
| 4101 ast_context()->ReturnInstruction(op, expr->id()); | 4107 ast_context()->ReturnInstruction(op, expr->id()); |
| 4102 return true; | 4108 return true; |
| 4103 } | 4109 } |
| 4104 break; | 4110 break; |
| 4105 case kMathPow: | 4111 case kMathPow: |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4162 | 4168 |
| 4163 if (graph()->info()->scope()->arguments() == NULL) return false; | 4169 if (graph()->info()->scope()->arguments() == NULL) return false; |
| 4164 | 4170 |
| 4165 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 4171 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 4166 if (!name->IsEqualTo(CStrVector("apply"))) return false; | 4172 if (!name->IsEqualTo(CStrVector("apply"))) return false; |
| 4167 | 4173 |
| 4168 ZoneList<Expression*>* args = expr->arguments(); | 4174 ZoneList<Expression*>* args = expr->arguments(); |
| 4169 if (args->length() != 2) return false; | 4175 if (args->length() != 2) return false; |
| 4170 | 4176 |
| 4171 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 4177 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
| 4172 if (arg_two == NULL) return false; | 4178 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
| 4173 HValue* arg_two_value = environment()->Lookup(arg_two->var()); | 4179 HValue* arg_two_value = environment()->Lookup(arg_two->var()); |
| 4174 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 4180 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
| 4175 | 4181 |
| 4176 if (!expr->IsMonomorphic()) return false; | 4182 if (!expr->IsMonomorphic()) return false; |
| 4177 | 4183 |
| 4178 // Found pattern f.apply(receiver, arguments). | 4184 // Found pattern f.apply(receiver, arguments). |
| 4179 VisitForValue(prop->obj()); | 4185 VisitForValue(prop->obj()); |
| 4180 if (HasStackOverflow()) return false; | 4186 if (HasStackOverflow()) return false; |
| 4181 HValue* function = Pop(); | 4187 HValue* function = Pop(); |
| 4182 VisitForValue(args->at(0)); | 4188 VisitForValue(args->at(0)); |
| (...skipping 1488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5671 } | 5677 } |
| 5672 | 5678 |
| 5673 #ifdef DEBUG | 5679 #ifdef DEBUG |
| 5674 if (graph_ != NULL) graph_->Verify(); | 5680 if (graph_ != NULL) graph_->Verify(); |
| 5675 if (chunk_ != NULL) chunk_->Verify(); | 5681 if (chunk_ != NULL) chunk_->Verify(); |
| 5676 if (allocator_ != NULL) allocator_->Verify(); | 5682 if (allocator_ != NULL) allocator_->Verify(); |
| 5677 #endif | 5683 #endif |
| 5678 } | 5684 } |
| 5679 | 5685 |
| 5680 } } // namespace v8::internal | 5686 } } // namespace v8::internal |
| OLD | NEW |