OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/crankshaft/hydrogen.h" | 5 #include "src/crankshaft/hydrogen.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/allocation-site-scopes.h" | 10 #include "src/allocation-site-scopes.h" |
(...skipping 5246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5257 | 5257 |
5258 if (!ast_context()->IsTest()) { | 5258 if (!ast_context()->IsTest()) { |
5259 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); | 5259 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); |
5260 set_current_block(join); | 5260 set_current_block(join); |
5261 if (join != NULL && !ast_context()->IsEffect()) { | 5261 if (join != NULL && !ast_context()->IsEffect()) { |
5262 return ast_context()->ReturnValue(Pop()); | 5262 return ast_context()->ReturnValue(Pop()); |
5263 } | 5263 } |
5264 } | 5264 } |
5265 } | 5265 } |
5266 | 5266 |
5267 bool HOptimizedGraphBuilder::CanInlineGlobalPropertyAccess( | |
5268 Variable* var, LookupIterator* it, PropertyAccessType access_type) { | |
5269 if (var->is_this()) return false; | |
5270 return CanInlineGlobalPropertyAccess(it, access_type); | |
5271 } | |
5272 | 5267 |
5273 bool HOptimizedGraphBuilder::CanInlineGlobalPropertyAccess( | 5268 HOptimizedGraphBuilder::GlobalPropertyAccess |
5274 LookupIterator* it, PropertyAccessType access_type) { | 5269 HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var, LookupIterator* it, |
5275 if (!current_info()->has_global_object()) { | 5270 PropertyAccessType access_type) { |
5276 return false; | 5271 if (var->is_this() || !current_info()->has_global_object()) { |
| 5272 return kUseGeneric; |
5277 } | 5273 } |
5278 | 5274 |
5279 switch (it->state()) { | 5275 switch (it->state()) { |
5280 case LookupIterator::ACCESSOR: | 5276 case LookupIterator::ACCESSOR: |
5281 case LookupIterator::ACCESS_CHECK: | 5277 case LookupIterator::ACCESS_CHECK: |
5282 case LookupIterator::INTERCEPTOR: | 5278 case LookupIterator::INTERCEPTOR: |
5283 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 5279 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
5284 case LookupIterator::NOT_FOUND: | 5280 case LookupIterator::NOT_FOUND: |
5285 return false; | 5281 return kUseGeneric; |
5286 case LookupIterator::DATA: | 5282 case LookupIterator::DATA: |
5287 if (access_type == STORE && it->IsReadOnly()) return false; | 5283 if (access_type == STORE && it->IsReadOnly()) return kUseGeneric; |
5288 if (!it->GetHolder<JSObject>()->IsJSGlobalObject()) return false; | 5284 if (!it->GetHolder<JSObject>()->IsJSGlobalObject()) return kUseGeneric; |
5289 return true; | 5285 return kUseCell; |
5290 case LookupIterator::JSPROXY: | 5286 case LookupIterator::JSPROXY: |
5291 case LookupIterator::TRANSITION: | 5287 case LookupIterator::TRANSITION: |
5292 UNREACHABLE(); | 5288 UNREACHABLE(); |
5293 } | 5289 } |
5294 UNREACHABLE(); | 5290 UNREACHABLE(); |
5295 return false; | 5291 return kUseGeneric; |
5296 } | 5292 } |
5297 | 5293 |
5298 | 5294 |
5299 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 5295 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
5300 DCHECK(var->IsContextSlot()); | 5296 DCHECK(var->IsContextSlot()); |
5301 HValue* context = environment()->context(); | 5297 HValue* context = environment()->context(); |
5302 int length = scope()->ContextChainLength(var->scope()); | 5298 int length = scope()->ContextChainLength(var->scope()); |
5303 while (length-- > 0) { | 5299 while (length-- > 0) { |
5304 context = Add<HLoadNamedField>( | 5300 context = Add<HLoadNamedField>( |
5305 context, nullptr, | 5301 context, nullptr, |
5306 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); | 5302 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); |
5307 } | 5303 } |
5308 return context; | 5304 return context; |
5309 } | 5305 } |
5310 | 5306 |
5311 void HOptimizedGraphBuilder::InlineGlobalPropertyLoad(LookupIterator* it, | |
5312 BailoutId ast_id) { | |
5313 Handle<PropertyCell> cell = it->GetPropertyCell(); | |
5314 top_info()->dependencies()->AssumePropertyCell(cell); | |
5315 auto cell_type = it->property_details().cell_type(); | |
5316 if (cell_type == PropertyCellType::kConstant || | |
5317 cell_type == PropertyCellType::kUndefined) { | |
5318 Handle<Object> constant_object(cell->value(), isolate()); | |
5319 if (constant_object->IsConsString()) { | |
5320 constant_object = String::Flatten(Handle<String>::cast(constant_object)); | |
5321 } | |
5322 HConstant* constant = New<HConstant>(constant_object); | |
5323 return ast_context()->ReturnInstruction(constant, ast_id); | |
5324 } else { | |
5325 auto access = HObjectAccess::ForPropertyCellValue(); | |
5326 UniqueSet<Map>* field_maps = nullptr; | |
5327 if (cell_type == PropertyCellType::kConstantType) { | |
5328 switch (cell->GetConstantType()) { | |
5329 case PropertyCellConstantType::kSmi: | |
5330 access = access.WithRepresentation(Representation::Smi()); | |
5331 break; | |
5332 case PropertyCellConstantType::kStableMap: { | |
5333 // Check that the map really is stable. The heap object could | |
5334 // have mutated without the cell updating state. In that case, | |
5335 // make no promises about the loaded value except that it's a | |
5336 // heap object. | |
5337 access = access.WithRepresentation(Representation::HeapObject()); | |
5338 Handle<Map> map(HeapObject::cast(cell->value())->map()); | |
5339 if (map->is_stable()) { | |
5340 field_maps = new (zone()) | |
5341 UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone()); | |
5342 } | |
5343 break; | |
5344 } | |
5345 } | |
5346 } | |
5347 HConstant* cell_constant = Add<HConstant>(cell); | |
5348 HLoadNamedField* instr; | |
5349 if (field_maps == nullptr) { | |
5350 instr = New<HLoadNamedField>(cell_constant, nullptr, access); | |
5351 } else { | |
5352 instr = New<HLoadNamedField>(cell_constant, nullptr, access, field_maps, | |
5353 HType::HeapObject()); | |
5354 } | |
5355 instr->ClearDependsOnFlag(kInobjectFields); | |
5356 instr->SetDependsOnFlag(kGlobalVars); | |
5357 return ast_context()->ReturnInstruction(instr, ast_id); | |
5358 } | |
5359 } | |
5360 | 5307 |
5361 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 5308 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
5362 DCHECK(!HasStackOverflow()); | 5309 DCHECK(!HasStackOverflow()); |
5363 DCHECK(current_block() != NULL); | 5310 DCHECK(current_block() != NULL); |
5364 DCHECK(current_block()->HasPredecessor()); | 5311 DCHECK(current_block()->HasPredecessor()); |
5365 Variable* variable = expr->var(); | 5312 Variable* variable = expr->var(); |
5366 switch (variable->location()) { | 5313 switch (variable->location()) { |
5367 case VariableLocation::UNALLOCATED: { | 5314 case VariableLocation::UNALLOCATED: { |
5368 if (IsLexicalVariableMode(variable->mode())) { | 5315 if (IsLexicalVariableMode(variable->mode())) { |
5369 // TODO(rossberg): should this be an DCHECK? | 5316 // TODO(rossberg): should this be an DCHECK? |
(...skipping 28 matching lines...) Expand all Loading... |
5398 return Bailout(kReferenceToUninitializedVariable); | 5345 return Bailout(kReferenceToUninitializedVariable); |
5399 } | 5346 } |
5400 HInstruction* result = New<HLoadNamedField>( | 5347 HInstruction* result = New<HLoadNamedField>( |
5401 Add<HConstant>(script_context), nullptr, | 5348 Add<HConstant>(script_context), nullptr, |
5402 HObjectAccess::ForContextSlot(lookup.slot_index)); | 5349 HObjectAccess::ForContextSlot(lookup.slot_index)); |
5403 return ast_context()->ReturnInstruction(result, expr->id()); | 5350 return ast_context()->ReturnInstruction(result, expr->id()); |
5404 } | 5351 } |
5405 } | 5352 } |
5406 | 5353 |
5407 LookupIterator it(global, variable->name(), LookupIterator::OWN); | 5354 LookupIterator it(global, variable->name(), LookupIterator::OWN); |
5408 if (CanInlineGlobalPropertyAccess(variable, &it, LOAD)) { | 5355 GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD); |
5409 InlineGlobalPropertyLoad(&it, expr->id()); | 5356 |
5410 return; | 5357 if (type == kUseCell) { |
| 5358 Handle<PropertyCell> cell = it.GetPropertyCell(); |
| 5359 top_info()->dependencies()->AssumePropertyCell(cell); |
| 5360 auto cell_type = it.property_details().cell_type(); |
| 5361 if (cell_type == PropertyCellType::kConstant || |
| 5362 cell_type == PropertyCellType::kUndefined) { |
| 5363 Handle<Object> constant_object(cell->value(), isolate()); |
| 5364 if (constant_object->IsConsString()) { |
| 5365 constant_object = |
| 5366 String::Flatten(Handle<String>::cast(constant_object)); |
| 5367 } |
| 5368 HConstant* constant = New<HConstant>(constant_object); |
| 5369 return ast_context()->ReturnInstruction(constant, expr->id()); |
| 5370 } else { |
| 5371 auto access = HObjectAccess::ForPropertyCellValue(); |
| 5372 UniqueSet<Map>* field_maps = nullptr; |
| 5373 if (cell_type == PropertyCellType::kConstantType) { |
| 5374 switch (cell->GetConstantType()) { |
| 5375 case PropertyCellConstantType::kSmi: |
| 5376 access = access.WithRepresentation(Representation::Smi()); |
| 5377 break; |
| 5378 case PropertyCellConstantType::kStableMap: { |
| 5379 // Check that the map really is stable. The heap object could |
| 5380 // have mutated without the cell updating state. In that case, |
| 5381 // make no promises about the loaded value except that it's a |
| 5382 // heap object. |
| 5383 access = |
| 5384 access.WithRepresentation(Representation::HeapObject()); |
| 5385 Handle<Map> map(HeapObject::cast(cell->value())->map()); |
| 5386 if (map->is_stable()) { |
| 5387 field_maps = new (zone()) |
| 5388 UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone()); |
| 5389 } |
| 5390 break; |
| 5391 } |
| 5392 } |
| 5393 } |
| 5394 HConstant* cell_constant = Add<HConstant>(cell); |
| 5395 HLoadNamedField* instr; |
| 5396 if (field_maps == nullptr) { |
| 5397 instr = New<HLoadNamedField>(cell_constant, nullptr, access); |
| 5398 } else { |
| 5399 instr = New<HLoadNamedField>(cell_constant, nullptr, access, |
| 5400 field_maps, HType::HeapObject()); |
| 5401 } |
| 5402 instr->ClearDependsOnFlag(kInobjectFields); |
| 5403 instr->SetDependsOnFlag(kGlobalVars); |
| 5404 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5405 } |
5411 } else { | 5406 } else { |
5412 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); | 5407 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); |
5413 | 5408 |
5414 HValue* vector_value = Add<HConstant>(vector); | 5409 HValue* vector_value = Add<HConstant>(vector); |
5415 HValue* slot_value = | 5410 HValue* slot_value = |
5416 Add<HConstant>(vector->GetIndex(expr->VariableFeedbackSlot())); | 5411 Add<HConstant>(vector->GetIndex(expr->VariableFeedbackSlot())); |
5417 Callable callable = CodeFactory::LoadGlobalICInOptimizedCode( | 5412 Callable callable = CodeFactory::LoadGlobalICInOptimizedCode( |
5418 isolate(), ast_context()->typeof_mode()); | 5413 isolate(), ast_context()->typeof_mode()); |
5419 HValue* stub = Add<HConstant>(callable.code()); | 5414 HValue* stub = Add<HConstant>(callable.code()); |
5420 HValue* values[] = {slot_value, vector_value}; | 5415 HValue* values[] = {slot_value, vector_value}; |
(...skipping 1083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6504 DCHECK(prop != NULL); | 6499 DCHECK(prop != NULL); |
6505 CHECK_ALIVE(VisitForValue(prop->obj())); | 6500 CHECK_ALIVE(VisitForValue(prop->obj())); |
6506 if (!prop->key()->IsPropertyName()) { | 6501 if (!prop->key()->IsPropertyName()) { |
6507 CHECK_ALIVE(VisitForValue(prop->key())); | 6502 CHECK_ALIVE(VisitForValue(prop->key())); |
6508 } | 6503 } |
6509 CHECK_ALIVE(VisitForValue(expr->value())); | 6504 CHECK_ALIVE(VisitForValue(expr->value())); |
6510 BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(), | 6505 BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(), |
6511 expr->AssignmentId(), expr->IsUninitialized()); | 6506 expr->AssignmentId(), expr->IsUninitialized()); |
6512 } | 6507 } |
6513 | 6508 |
6514 HInstruction* HOptimizedGraphBuilder::InlineGlobalPropertyStore( | |
6515 LookupIterator* it, HValue* value, BailoutId ast_id) { | |
6516 Handle<PropertyCell> cell = it->GetPropertyCell(); | |
6517 top_info()->dependencies()->AssumePropertyCell(cell); | |
6518 auto cell_type = it->property_details().cell_type(); | |
6519 if (cell_type == PropertyCellType::kConstant || | |
6520 cell_type == PropertyCellType::kUndefined) { | |
6521 Handle<Object> constant(cell->value(), isolate()); | |
6522 if (value->IsConstant()) { | |
6523 HConstant* c_value = HConstant::cast(value); | |
6524 if (!constant.is_identical_to(c_value->handle(isolate()))) { | |
6525 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, | |
6526 Deoptimizer::EAGER); | |
6527 } | |
6528 } else { | |
6529 HValue* c_constant = Add<HConstant>(constant); | |
6530 IfBuilder builder(this); | |
6531 if (constant->IsNumber()) { | |
6532 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); | |
6533 } else { | |
6534 builder.If<HCompareObjectEqAndBranch>(value, c_constant); | |
6535 } | |
6536 builder.Then(); | |
6537 builder.Else(); | |
6538 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, | |
6539 Deoptimizer::EAGER); | |
6540 builder.End(); | |
6541 } | |
6542 } | |
6543 HConstant* cell_constant = Add<HConstant>(cell); | |
6544 auto access = HObjectAccess::ForPropertyCellValue(); | |
6545 if (cell_type == PropertyCellType::kConstantType) { | |
6546 switch (cell->GetConstantType()) { | |
6547 case PropertyCellConstantType::kSmi: | |
6548 access = access.WithRepresentation(Representation::Smi()); | |
6549 break; | |
6550 case PropertyCellConstantType::kStableMap: { | |
6551 // The map may no longer be stable, deopt if it's ever different from | |
6552 // what is currently there, which will allow for restablization. | |
6553 Handle<Map> map(HeapObject::cast(cell->value())->map()); | |
6554 Add<HCheckHeapObject>(value); | |
6555 value = Add<HCheckMaps>(value, map); | |
6556 access = access.WithRepresentation(Representation::HeapObject()); | |
6557 break; | |
6558 } | |
6559 } | |
6560 } | |
6561 HInstruction* instr = New<HStoreNamedField>(cell_constant, access, value); | |
6562 instr->ClearChangesFlag(kInobjectFields); | |
6563 instr->SetChangesFlag(kGlobalVars); | |
6564 return instr; | |
6565 } | |
6566 | 6509 |
6567 // Because not every expression has a position and there is not common | 6510 // Because not every expression has a position and there is not common |
6568 // superclass of Assignment and CountOperation, we cannot just pass the | 6511 // superclass of Assignment and CountOperation, we cannot just pass the |
6569 // owning expression instead of position and ast_id separately. | 6512 // owning expression instead of position and ast_id separately. |
6570 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 6513 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
6571 Variable* var, HValue* value, FeedbackVectorSlot slot, BailoutId ast_id) { | 6514 Variable* var, HValue* value, FeedbackVectorSlot slot, BailoutId ast_id) { |
6572 Handle<JSGlobalObject> global(current_info()->global_object()); | 6515 Handle<JSGlobalObject> global(current_info()->global_object()); |
6573 | 6516 |
6574 // Lookup in script contexts. | 6517 // Lookup in script contexts. |
6575 { | 6518 { |
(...skipping 20 matching lines...) Expand all Loading... |
6596 Add<HConstant>(script_context), | 6539 Add<HConstant>(script_context), |
6597 HObjectAccess::ForContextSlot(lookup.slot_index), value); | 6540 HObjectAccess::ForContextSlot(lookup.slot_index), value); |
6598 USE(instr); | 6541 USE(instr); |
6599 DCHECK(instr->HasObservableSideEffects()); | 6542 DCHECK(instr->HasObservableSideEffects()); |
6600 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6543 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6601 return; | 6544 return; |
6602 } | 6545 } |
6603 } | 6546 } |
6604 | 6547 |
6605 LookupIterator it(global, var->name(), LookupIterator::OWN); | 6548 LookupIterator it(global, var->name(), LookupIterator::OWN); |
6606 if (CanInlineGlobalPropertyAccess(var, &it, STORE)) { | 6549 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); |
6607 HInstruction* instr = InlineGlobalPropertyStore(&it, value, ast_id); | 6550 if (type == kUseCell) { |
6608 AddInstruction(instr); | 6551 Handle<PropertyCell> cell = it.GetPropertyCell(); |
| 6552 top_info()->dependencies()->AssumePropertyCell(cell); |
| 6553 auto cell_type = it.property_details().cell_type(); |
| 6554 if (cell_type == PropertyCellType::kConstant || |
| 6555 cell_type == PropertyCellType::kUndefined) { |
| 6556 Handle<Object> constant(cell->value(), isolate()); |
| 6557 if (value->IsConstant()) { |
| 6558 HConstant* c_value = HConstant::cast(value); |
| 6559 if (!constant.is_identical_to(c_value->handle(isolate()))) { |
| 6560 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, |
| 6561 Deoptimizer::EAGER); |
| 6562 } |
| 6563 } else { |
| 6564 HValue* c_constant = Add<HConstant>(constant); |
| 6565 IfBuilder builder(this); |
| 6566 if (constant->IsNumber()) { |
| 6567 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); |
| 6568 } else { |
| 6569 builder.If<HCompareObjectEqAndBranch>(value, c_constant); |
| 6570 } |
| 6571 builder.Then(); |
| 6572 builder.Else(); |
| 6573 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, |
| 6574 Deoptimizer::EAGER); |
| 6575 builder.End(); |
| 6576 } |
| 6577 } |
| 6578 HConstant* cell_constant = Add<HConstant>(cell); |
| 6579 auto access = HObjectAccess::ForPropertyCellValue(); |
| 6580 if (cell_type == PropertyCellType::kConstantType) { |
| 6581 switch (cell->GetConstantType()) { |
| 6582 case PropertyCellConstantType::kSmi: |
| 6583 access = access.WithRepresentation(Representation::Smi()); |
| 6584 break; |
| 6585 case PropertyCellConstantType::kStableMap: { |
| 6586 // The map may no longer be stable, deopt if it's ever different from |
| 6587 // what is currently there, which will allow for restablization. |
| 6588 Handle<Map> map(HeapObject::cast(cell->value())->map()); |
| 6589 Add<HCheckHeapObject>(value); |
| 6590 value = Add<HCheckMaps>(value, map); |
| 6591 access = access.WithRepresentation(Representation::HeapObject()); |
| 6592 break; |
| 6593 } |
| 6594 } |
| 6595 } |
| 6596 HInstruction* instr = Add<HStoreNamedField>(cell_constant, access, value); |
| 6597 instr->ClearChangesFlag(kInobjectFields); |
| 6598 instr->SetChangesFlag(kGlobalVars); |
6609 if (instr->HasObservableSideEffects()) { | 6599 if (instr->HasObservableSideEffects()) { |
6610 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6600 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6611 } | 6601 } |
6612 } else { | 6602 } else { |
6613 HValue* global_object = Add<HLoadNamedField>( | 6603 HValue* global_object = Add<HLoadNamedField>( |
6614 BuildGetNativeContext(), nullptr, | 6604 BuildGetNativeContext(), nullptr, |
6615 HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX)); | 6605 HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX)); |
6616 Handle<TypeFeedbackVector> vector = | 6606 Handle<TypeFeedbackVector> vector = |
6617 handle(current_feedback_vector(), isolate()); | 6607 handle(current_feedback_vector(), isolate()); |
6618 HValue* name = Add<HConstant>(var->name()); | 6608 HValue* name = Add<HConstant>(var->name()); |
(...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7521 | 7511 |
7522 HValue* HOptimizedGraphBuilder::BuildNamedAccess( | 7512 HValue* HOptimizedGraphBuilder::BuildNamedAccess( |
7523 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, | 7513 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, |
7524 Expression* expr, FeedbackVectorSlot slot, HValue* object, | 7514 Expression* expr, FeedbackVectorSlot slot, HValue* object, |
7525 Handle<Name> name, HValue* value, bool is_uninitialized) { | 7515 Handle<Name> name, HValue* value, bool is_uninitialized) { |
7526 SmallMapList* maps; | 7516 SmallMapList* maps; |
7527 ComputeReceiverTypes(expr, object, &maps, this); | 7517 ComputeReceiverTypes(expr, object, &maps, this); |
7528 DCHECK(maps != NULL); | 7518 DCHECK(maps != NULL); |
7529 | 7519 |
7530 if (maps->length() > 0) { | 7520 if (maps->length() > 0) { |
7531 Handle<JSGlobalObject> global_object(current_info()->global_object()); | |
7532 Handle<Context> current_context(current_info()->context()); | |
7533 Handle<JSObject> global_proxy(current_context->global_proxy()); | |
7534 | |
7535 // Check for special case: Access via a single map to the global proxy | |
7536 // can also be handled monomorphically. | |
7537 Handle<Object> map_constructor = | |
7538 handle(maps->first()->GetConstructor(), isolate()); | |
7539 if (map_constructor->IsJSFunction()) { | |
7540 Handle<Context> map_context = | |
7541 handle(Handle<JSFunction>::cast(map_constructor)->context()); | |
7542 bool is_global_proxy_access = | |
7543 maps->length() == 1 && // More than one map, fallback to polymorphic? | |
7544 maps->first()->IsJSGlobalProxyMap() && | |
7545 isolate()->MayAccess(map_context, global_proxy); | |
7546 | |
7547 if (is_global_proxy_access) { | |
7548 LookupIterator it(global_object, name, LookupIterator::OWN); | |
7549 if (CanInlineGlobalPropertyAccess(&it, access)) { | |
7550 BuildCheckHeapObject(object); | |
7551 Add<HCheckMaps>(object, maps); | |
7552 if (access == LOAD) { | |
7553 InlineGlobalPropertyLoad(&it, expr->id()); | |
7554 return nullptr; | |
7555 } else { | |
7556 return InlineGlobalPropertyStore(&it, value, expr->id()); | |
7557 } | |
7558 } | |
7559 } | |
7560 } | |
7561 | |
7562 PropertyAccessInfo info(this, access, maps->first(), name); | 7521 PropertyAccessInfo info(this, access, maps->first(), name); |
7563 if (!info.CanAccessAsMonomorphic(maps)) { | 7522 if (!info.CanAccessAsMonomorphic(maps)) { |
7564 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id, | 7523 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id, |
7565 object, value, maps, name); | 7524 object, value, maps, name); |
7566 return NULL; | 7525 return NULL; |
7567 } | 7526 } |
7568 | 7527 |
7569 HValue* checked_object; | 7528 HValue* checked_object; |
7570 // AstType::Number() is only supported by polymorphic load/call handling. | 7529 // AstType::Number() is only supported by polymorphic load/call handling. |
7571 DCHECK(!info.IsNumberType()); | 7530 DCHECK(!info.IsNumberType()); |
(...skipping 5551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13123 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13082 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13124 } | 13083 } |
13125 | 13084 |
13126 #ifdef DEBUG | 13085 #ifdef DEBUG |
13127 graph_->Verify(false); // No full verify. | 13086 graph_->Verify(false); // No full verify. |
13128 #endif | 13087 #endif |
13129 } | 13088 } |
13130 | 13089 |
13131 } // namespace internal | 13090 } // namespace internal |
13132 } // namespace v8 | 13091 } // namespace v8 |
OLD | NEW |