| 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 5181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5192 | 5192 |
| 5193 if (!ast_context()->IsTest()) { | 5193 if (!ast_context()->IsTest()) { |
| 5194 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); | 5194 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); |
| 5195 set_current_block(join); | 5195 set_current_block(join); |
| 5196 if (join != NULL && !ast_context()->IsEffect()) { | 5196 if (join != NULL && !ast_context()->IsEffect()) { |
| 5197 return ast_context()->ReturnValue(Pop()); | 5197 return ast_context()->ReturnValue(Pop()); |
| 5198 } | 5198 } |
| 5199 } | 5199 } |
| 5200 } | 5200 } |
| 5201 | 5201 |
| 5202 bool HOptimizedGraphBuilder::CanInlineGlobalPropertyAccess( |
| 5203 Variable* var, LookupIterator* it, PropertyAccessType access_type) { |
| 5204 if (var->is_this()) return false; |
| 5205 return CanInlineGlobalPropertyAccess(it, access_type); |
| 5206 } |
| 5202 | 5207 |
| 5203 HOptimizedGraphBuilder::GlobalPropertyAccess | 5208 bool HOptimizedGraphBuilder::CanInlineGlobalPropertyAccess( |
| 5204 HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var, LookupIterator* it, | 5209 LookupIterator* it, PropertyAccessType access_type) { |
| 5205 PropertyAccessType access_type) { | 5210 if (!current_info()->has_global_object()) { |
| 5206 if (var->is_this() || !current_info()->has_global_object()) { | 5211 return false; |
| 5207 return kUseGeneric; | |
| 5208 } | 5212 } |
| 5209 | 5213 |
| 5210 switch (it->state()) { | 5214 switch (it->state()) { |
| 5211 case LookupIterator::ACCESSOR: | 5215 case LookupIterator::ACCESSOR: |
| 5212 case LookupIterator::ACCESS_CHECK: | 5216 case LookupIterator::ACCESS_CHECK: |
| 5213 case LookupIterator::INTERCEPTOR: | 5217 case LookupIterator::INTERCEPTOR: |
| 5214 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 5218 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
| 5215 case LookupIterator::NOT_FOUND: | 5219 case LookupIterator::NOT_FOUND: |
| 5216 return kUseGeneric; | 5220 return false; |
| 5217 case LookupIterator::DATA: | 5221 case LookupIterator::DATA: |
| 5218 if (access_type == STORE && it->IsReadOnly()) return kUseGeneric; | 5222 if (access_type == STORE && it->IsReadOnly()) return false; |
| 5219 if (!it->GetHolder<JSObject>()->IsJSGlobalObject()) return kUseGeneric; | 5223 if (!it->GetHolder<JSObject>()->IsJSGlobalObject()) return false; |
| 5220 return kUseCell; | 5224 return true; |
| 5221 case LookupIterator::JSPROXY: | 5225 case LookupIterator::JSPROXY: |
| 5222 case LookupIterator::TRANSITION: | 5226 case LookupIterator::TRANSITION: |
| 5223 UNREACHABLE(); | 5227 UNREACHABLE(); |
| 5224 } | 5228 } |
| 5225 UNREACHABLE(); | 5229 UNREACHABLE(); |
| 5226 return kUseGeneric; | 5230 return false; |
| 5227 } | 5231 } |
| 5228 | 5232 |
| 5229 | 5233 |
| 5230 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 5234 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
| 5231 DCHECK(var->IsContextSlot()); | 5235 DCHECK(var->IsContextSlot()); |
| 5232 HValue* context = environment()->context(); | 5236 HValue* context = environment()->context(); |
| 5233 int length = scope()->ContextChainLength(var->scope()); | 5237 int length = scope()->ContextChainLength(var->scope()); |
| 5234 while (length-- > 0) { | 5238 while (length-- > 0) { |
| 5235 context = Add<HLoadNamedField>( | 5239 context = Add<HLoadNamedField>( |
| 5236 context, nullptr, | 5240 context, nullptr, |
| 5237 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); | 5241 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); |
| 5238 } | 5242 } |
| 5239 return context; | 5243 return context; |
| 5240 } | 5244 } |
| 5241 | 5245 |
| 5246 void HOptimizedGraphBuilder::InlineGlobalPropertyLoad(LookupIterator* it, |
| 5247 BailoutId ast_id) { |
| 5248 Handle<PropertyCell> cell = it->GetPropertyCell(); |
| 5249 top_info()->dependencies()->AssumePropertyCell(cell); |
| 5250 auto cell_type = it->property_details().cell_type(); |
| 5251 if (cell_type == PropertyCellType::kConstant || |
| 5252 cell_type == PropertyCellType::kUndefined) { |
| 5253 Handle<Object> constant_object(cell->value(), isolate()); |
| 5254 if (constant_object->IsConsString()) { |
| 5255 constant_object = String::Flatten(Handle<String>::cast(constant_object)); |
| 5256 } |
| 5257 HConstant* constant = New<HConstant>(constant_object); |
| 5258 return ast_context()->ReturnInstruction(constant, ast_id); |
| 5259 } else { |
| 5260 auto access = HObjectAccess::ForPropertyCellValue(); |
| 5261 UniqueSet<Map>* field_maps = nullptr; |
| 5262 if (cell_type == PropertyCellType::kConstantType) { |
| 5263 switch (cell->GetConstantType()) { |
| 5264 case PropertyCellConstantType::kSmi: |
| 5265 access = access.WithRepresentation(Representation::Smi()); |
| 5266 break; |
| 5267 case PropertyCellConstantType::kStableMap: { |
| 5268 // Check that the map really is stable. The heap object could |
| 5269 // have mutated without the cell updating state. In that case, |
| 5270 // make no promises about the loaded value except that it's a |
| 5271 // heap object. |
| 5272 access = access.WithRepresentation(Representation::HeapObject()); |
| 5273 Handle<Map> map(HeapObject::cast(cell->value())->map()); |
| 5274 if (map->is_stable()) { |
| 5275 field_maps = new (zone()) |
| 5276 UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone()); |
| 5277 } |
| 5278 break; |
| 5279 } |
| 5280 } |
| 5281 } |
| 5282 HConstant* cell_constant = Add<HConstant>(cell); |
| 5283 HLoadNamedField* instr; |
| 5284 if (field_maps == nullptr) { |
| 5285 instr = New<HLoadNamedField>(cell_constant, nullptr, access); |
| 5286 } else { |
| 5287 instr = New<HLoadNamedField>(cell_constant, nullptr, access, field_maps, |
| 5288 HType::HeapObject()); |
| 5289 } |
| 5290 instr->ClearDependsOnFlag(kInobjectFields); |
| 5291 instr->SetDependsOnFlag(kGlobalVars); |
| 5292 return ast_context()->ReturnInstruction(instr, ast_id); |
| 5293 } |
| 5294 } |
| 5242 | 5295 |
| 5243 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 5296 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 5244 DCHECK(!HasStackOverflow()); | 5297 DCHECK(!HasStackOverflow()); |
| 5245 DCHECK(current_block() != NULL); | 5298 DCHECK(current_block() != NULL); |
| 5246 DCHECK(current_block()->HasPredecessor()); | 5299 DCHECK(current_block()->HasPredecessor()); |
| 5247 Variable* variable = expr->var(); | 5300 Variable* variable = expr->var(); |
| 5248 switch (variable->location()) { | 5301 switch (variable->location()) { |
| 5249 case VariableLocation::UNALLOCATED: { | 5302 case VariableLocation::UNALLOCATED: { |
| 5250 if (IsLexicalVariableMode(variable->mode())) { | 5303 if (IsLexicalVariableMode(variable->mode())) { |
| 5251 // TODO(rossberg): should this be an DCHECK? | 5304 // TODO(rossberg): should this be an DCHECK? |
| (...skipping 28 matching lines...) Expand all Loading... |
| 5280 return Bailout(kReferenceToUninitializedVariable); | 5333 return Bailout(kReferenceToUninitializedVariable); |
| 5281 } | 5334 } |
| 5282 HInstruction* result = New<HLoadNamedField>( | 5335 HInstruction* result = New<HLoadNamedField>( |
| 5283 Add<HConstant>(script_context), nullptr, | 5336 Add<HConstant>(script_context), nullptr, |
| 5284 HObjectAccess::ForContextSlot(lookup.slot_index)); | 5337 HObjectAccess::ForContextSlot(lookup.slot_index)); |
| 5285 return ast_context()->ReturnInstruction(result, expr->id()); | 5338 return ast_context()->ReturnInstruction(result, expr->id()); |
| 5286 } | 5339 } |
| 5287 } | 5340 } |
| 5288 | 5341 |
| 5289 LookupIterator it(global, variable->name(), LookupIterator::OWN); | 5342 LookupIterator it(global, variable->name(), LookupIterator::OWN); |
| 5290 GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD); | 5343 if (CanInlineGlobalPropertyAccess(variable, &it, LOAD)) { |
| 5291 | 5344 InlineGlobalPropertyLoad(&it, expr->id()); |
| 5292 if (type == kUseCell) { | 5345 return; |
| 5293 Handle<PropertyCell> cell = it.GetPropertyCell(); | |
| 5294 top_info()->dependencies()->AssumePropertyCell(cell); | |
| 5295 auto cell_type = it.property_details().cell_type(); | |
| 5296 if (cell_type == PropertyCellType::kConstant || | |
| 5297 cell_type == PropertyCellType::kUndefined) { | |
| 5298 Handle<Object> constant_object(cell->value(), isolate()); | |
| 5299 if (constant_object->IsConsString()) { | |
| 5300 constant_object = | |
| 5301 String::Flatten(Handle<String>::cast(constant_object)); | |
| 5302 } | |
| 5303 HConstant* constant = New<HConstant>(constant_object); | |
| 5304 return ast_context()->ReturnInstruction(constant, expr->id()); | |
| 5305 } else { | |
| 5306 auto access = HObjectAccess::ForPropertyCellValue(); | |
| 5307 UniqueSet<Map>* field_maps = nullptr; | |
| 5308 if (cell_type == PropertyCellType::kConstantType) { | |
| 5309 switch (cell->GetConstantType()) { | |
| 5310 case PropertyCellConstantType::kSmi: | |
| 5311 access = access.WithRepresentation(Representation::Smi()); | |
| 5312 break; | |
| 5313 case PropertyCellConstantType::kStableMap: { | |
| 5314 // Check that the map really is stable. The heap object could | |
| 5315 // have mutated without the cell updating state. In that case, | |
| 5316 // make no promises about the loaded value except that it's a | |
| 5317 // heap object. | |
| 5318 access = | |
| 5319 access.WithRepresentation(Representation::HeapObject()); | |
| 5320 Handle<Map> map(HeapObject::cast(cell->value())->map()); | |
| 5321 if (map->is_stable()) { | |
| 5322 field_maps = new (zone()) | |
| 5323 UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone()); | |
| 5324 } | |
| 5325 break; | |
| 5326 } | |
| 5327 } | |
| 5328 } | |
| 5329 HConstant* cell_constant = Add<HConstant>(cell); | |
| 5330 HLoadNamedField* instr; | |
| 5331 if (field_maps == nullptr) { | |
| 5332 instr = New<HLoadNamedField>(cell_constant, nullptr, access); | |
| 5333 } else { | |
| 5334 instr = New<HLoadNamedField>(cell_constant, nullptr, access, | |
| 5335 field_maps, HType::HeapObject()); | |
| 5336 } | |
| 5337 instr->ClearDependsOnFlag(kInobjectFields); | |
| 5338 instr->SetDependsOnFlag(kGlobalVars); | |
| 5339 return ast_context()->ReturnInstruction(instr, expr->id()); | |
| 5340 } | |
| 5341 } else { | 5346 } else { |
| 5342 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); | 5347 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); |
| 5343 | 5348 |
| 5344 HValue* vector_value = Add<HConstant>(vector); | 5349 HValue* vector_value = Add<HConstant>(vector); |
| 5345 HValue* slot_value = | 5350 HValue* slot_value = |
| 5346 Add<HConstant>(vector->GetIndex(expr->VariableFeedbackSlot())); | 5351 Add<HConstant>(vector->GetIndex(expr->VariableFeedbackSlot())); |
| 5347 Callable callable = CodeFactory::LoadGlobalICInOptimizedCode( | 5352 Callable callable = CodeFactory::LoadGlobalICInOptimizedCode( |
| 5348 isolate(), ast_context()->typeof_mode()); | 5353 isolate(), ast_context()->typeof_mode()); |
| 5349 HValue* stub = Add<HConstant>(callable.code()); | 5354 HValue* stub = Add<HConstant>(callable.code()); |
| 5350 HValue* values[] = {slot_value, vector_value}; | 5355 HValue* values[] = {slot_value, vector_value}; |
| (...skipping 1083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6434 DCHECK(prop != NULL); | 6439 DCHECK(prop != NULL); |
| 6435 CHECK_ALIVE(VisitForValue(prop->obj())); | 6440 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 6436 if (!prop->key()->IsPropertyName()) { | 6441 if (!prop->key()->IsPropertyName()) { |
| 6437 CHECK_ALIVE(VisitForValue(prop->key())); | 6442 CHECK_ALIVE(VisitForValue(prop->key())); |
| 6438 } | 6443 } |
| 6439 CHECK_ALIVE(VisitForValue(expr->value())); | 6444 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6440 BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(), | 6445 BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(), |
| 6441 expr->AssignmentId(), expr->IsUninitialized()); | 6446 expr->AssignmentId(), expr->IsUninitialized()); |
| 6442 } | 6447 } |
| 6443 | 6448 |
| 6449 HInstruction* HOptimizedGraphBuilder::InlineGlobalPropertyStore( |
| 6450 LookupIterator* it, HValue* value, BailoutId ast_id) { |
| 6451 Handle<PropertyCell> cell = it->GetPropertyCell(); |
| 6452 top_info()->dependencies()->AssumePropertyCell(cell); |
| 6453 auto cell_type = it->property_details().cell_type(); |
| 6454 if (cell_type == PropertyCellType::kConstant || |
| 6455 cell_type == PropertyCellType::kUndefined) { |
| 6456 Handle<Object> constant(cell->value(), isolate()); |
| 6457 if (value->IsConstant()) { |
| 6458 HConstant* c_value = HConstant::cast(value); |
| 6459 if (!constant.is_identical_to(c_value->handle(isolate()))) { |
| 6460 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, |
| 6461 Deoptimizer::EAGER); |
| 6462 } |
| 6463 } else { |
| 6464 HValue* c_constant = Add<HConstant>(constant); |
| 6465 IfBuilder builder(this); |
| 6466 if (constant->IsNumber()) { |
| 6467 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); |
| 6468 } else { |
| 6469 builder.If<HCompareObjectEqAndBranch>(value, c_constant); |
| 6470 } |
| 6471 builder.Then(); |
| 6472 builder.Else(); |
| 6473 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, |
| 6474 Deoptimizer::EAGER); |
| 6475 builder.End(); |
| 6476 } |
| 6477 } |
| 6478 HConstant* cell_constant = Add<HConstant>(cell); |
| 6479 auto access = HObjectAccess::ForPropertyCellValue(); |
| 6480 if (cell_type == PropertyCellType::kConstantType) { |
| 6481 switch (cell->GetConstantType()) { |
| 6482 case PropertyCellConstantType::kSmi: |
| 6483 access = access.WithRepresentation(Representation::Smi()); |
| 6484 break; |
| 6485 case PropertyCellConstantType::kStableMap: { |
| 6486 // First check that the previous value of the {cell} still has the |
| 6487 // map that we are about to check the new {value} for. If not, then |
| 6488 // the stable map assumption was invalidated and we cannot continue |
| 6489 // with the optimized code. |
| 6490 Handle<HeapObject> cell_value(HeapObject::cast(cell->value())); |
| 6491 Handle<Map> cell_value_map(cell_value->map()); |
| 6492 if (!cell_value_map->is_stable()) { |
| 6493 Bailout(kUnstableConstantTypeHeapObject); |
| 6494 return nullptr; |
| 6495 } |
| 6496 top_info()->dependencies()->AssumeMapStable(cell_value_map); |
| 6497 // Now check that the new {value} is a HeapObject with the same map |
| 6498 Add<HCheckHeapObject>(value); |
| 6499 value = Add<HCheckMaps>(value, cell_value_map); |
| 6500 access = access.WithRepresentation(Representation::HeapObject()); |
| 6501 break; |
| 6502 } |
| 6503 } |
| 6504 } |
| 6505 HInstruction* instr = New<HStoreNamedField>(cell_constant, access, value); |
| 6506 instr->ClearChangesFlag(kInobjectFields); |
| 6507 instr->SetChangesFlag(kGlobalVars); |
| 6508 return instr; |
| 6509 } |
| 6444 | 6510 |
| 6445 // Because not every expression has a position and there is not common | 6511 // Because not every expression has a position and there is not common |
| 6446 // superclass of Assignment and CountOperation, we cannot just pass the | 6512 // superclass of Assignment and CountOperation, we cannot just pass the |
| 6447 // owning expression instead of position and ast_id separately. | 6513 // owning expression instead of position and ast_id separately. |
| 6448 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 6514 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
| 6449 Variable* var, HValue* value, FeedbackVectorSlot slot, BailoutId ast_id) { | 6515 Variable* var, HValue* value, FeedbackVectorSlot slot, BailoutId ast_id) { |
| 6450 Handle<JSGlobalObject> global(current_info()->global_object()); | 6516 Handle<JSGlobalObject> global(current_info()->global_object()); |
| 6451 | 6517 |
| 6452 // Lookup in script contexts. | 6518 // Lookup in script contexts. |
| 6453 { | 6519 { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 6474 Add<HConstant>(script_context), | 6540 Add<HConstant>(script_context), |
| 6475 HObjectAccess::ForContextSlot(lookup.slot_index), value); | 6541 HObjectAccess::ForContextSlot(lookup.slot_index), value); |
| 6476 USE(instr); | 6542 USE(instr); |
| 6477 DCHECK(instr->HasObservableSideEffects()); | 6543 DCHECK(instr->HasObservableSideEffects()); |
| 6478 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6544 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6479 return; | 6545 return; |
| 6480 } | 6546 } |
| 6481 } | 6547 } |
| 6482 | 6548 |
| 6483 LookupIterator it(global, var->name(), LookupIterator::OWN); | 6549 LookupIterator it(global, var->name(), LookupIterator::OWN); |
| 6484 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); | 6550 if (CanInlineGlobalPropertyAccess(var, &it, STORE)) { |
| 6485 if (type == kUseCell) { | 6551 HInstruction* instr = InlineGlobalPropertyStore(&it, value, ast_id); |
| 6486 Handle<PropertyCell> cell = it.GetPropertyCell(); | 6552 if (!instr) return; |
| 6487 top_info()->dependencies()->AssumePropertyCell(cell); | 6553 AddInstruction(instr); |
| 6488 auto cell_type = it.property_details().cell_type(); | |
| 6489 if (cell_type == PropertyCellType::kConstant || | |
| 6490 cell_type == PropertyCellType::kUndefined) { | |
| 6491 Handle<Object> constant(cell->value(), isolate()); | |
| 6492 if (value->IsConstant()) { | |
| 6493 HConstant* c_value = HConstant::cast(value); | |
| 6494 if (!constant.is_identical_to(c_value->handle(isolate()))) { | |
| 6495 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, | |
| 6496 Deoptimizer::EAGER); | |
| 6497 } | |
| 6498 } else { | |
| 6499 HValue* c_constant = Add<HConstant>(constant); | |
| 6500 IfBuilder builder(this); | |
| 6501 if (constant->IsNumber()) { | |
| 6502 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); | |
| 6503 } else { | |
| 6504 builder.If<HCompareObjectEqAndBranch>(value, c_constant); | |
| 6505 } | |
| 6506 builder.Then(); | |
| 6507 builder.Else(); | |
| 6508 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, | |
| 6509 Deoptimizer::EAGER); | |
| 6510 builder.End(); | |
| 6511 } | |
| 6512 } | |
| 6513 HConstant* cell_constant = Add<HConstant>(cell); | |
| 6514 auto access = HObjectAccess::ForPropertyCellValue(); | |
| 6515 if (cell_type == PropertyCellType::kConstantType) { | |
| 6516 switch (cell->GetConstantType()) { | |
| 6517 case PropertyCellConstantType::kSmi: | |
| 6518 access = access.WithRepresentation(Representation::Smi()); | |
| 6519 break; | |
| 6520 case PropertyCellConstantType::kStableMap: { | |
| 6521 // First check that the previous value of the {cell} still has the | |
| 6522 // map that we are about to check the new {value} for. If not, then | |
| 6523 // the stable map assumption was invalidated and we cannot continue | |
| 6524 // with the optimized code. | |
| 6525 Handle<HeapObject> cell_value(HeapObject::cast(cell->value())); | |
| 6526 Handle<Map> cell_value_map(cell_value->map()); | |
| 6527 if (!cell_value_map->is_stable()) { | |
| 6528 return Bailout(kUnstableConstantTypeHeapObject); | |
| 6529 } | |
| 6530 top_info()->dependencies()->AssumeMapStable(cell_value_map); | |
| 6531 // Now check that the new {value} is a HeapObject with the same map. | |
| 6532 Add<HCheckHeapObject>(value); | |
| 6533 value = Add<HCheckMaps>(value, cell_value_map); | |
| 6534 access = access.WithRepresentation(Representation::HeapObject()); | |
| 6535 break; | |
| 6536 } | |
| 6537 } | |
| 6538 } | |
| 6539 HInstruction* instr = Add<HStoreNamedField>(cell_constant, access, value); | |
| 6540 instr->ClearChangesFlag(kInobjectFields); | |
| 6541 instr->SetChangesFlag(kGlobalVars); | |
| 6542 if (instr->HasObservableSideEffects()) { | 6554 if (instr->HasObservableSideEffects()) { |
| 6543 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6555 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6544 } | 6556 } |
| 6545 } else { | 6557 } else { |
| 6546 HValue* global_object = Add<HLoadNamedField>( | 6558 HValue* global_object = Add<HLoadNamedField>( |
| 6547 BuildGetNativeContext(), nullptr, | 6559 BuildGetNativeContext(), nullptr, |
| 6548 HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX)); | 6560 HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX)); |
| 6549 Handle<TypeFeedbackVector> vector = | 6561 Handle<TypeFeedbackVector> vector = |
| 6550 handle(current_feedback_vector(), isolate()); | 6562 handle(current_feedback_vector(), isolate()); |
| 6551 HValue* name = Add<HConstant>(var->name()); | 6563 HValue* name = Add<HConstant>(var->name()); |
| (...skipping 901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7453 } | 7465 } |
| 7454 | 7466 |
| 7455 HValue* HOptimizedGraphBuilder::BuildNamedAccess( | 7467 HValue* HOptimizedGraphBuilder::BuildNamedAccess( |
| 7456 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, | 7468 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, |
| 7457 Expression* expr, FeedbackVectorSlot slot, HValue* object, | 7469 Expression* expr, FeedbackVectorSlot slot, HValue* object, |
| 7458 Handle<Name> name, HValue* value, bool is_uninitialized) { | 7470 Handle<Name> name, HValue* value, bool is_uninitialized) { |
| 7459 SmallMapList* maps; | 7471 SmallMapList* maps; |
| 7460 ComputeReceiverTypes(expr, object, &maps, this); | 7472 ComputeReceiverTypes(expr, object, &maps, this); |
| 7461 DCHECK(maps != NULL); | 7473 DCHECK(maps != NULL); |
| 7462 | 7474 |
| 7475 // Check for special case: Access via a single map to the global proxy |
| 7476 // can also be handled monomorphically. |
| 7463 if (maps->length() > 0) { | 7477 if (maps->length() > 0) { |
| 7478 Handle<Object> map_constructor = |
| 7479 handle(maps->first()->GetConstructor(), isolate()); |
| 7480 if (map_constructor->IsJSFunction()) { |
| 7481 Handle<Context> map_context = |
| 7482 handle(Handle<JSFunction>::cast(map_constructor)->context()); |
| 7483 Handle<Context> current_context(current_info()->context()); |
| 7484 bool is_same_context_global_proxy_access = |
| 7485 maps->length() == 1 && // >1 map => fallback to polymorphic |
| 7486 maps->first()->IsJSGlobalProxyMap() && |
| 7487 (*map_context == *current_context); |
| 7488 if (is_same_context_global_proxy_access) { |
| 7489 Handle<JSGlobalObject> global_object(current_info()->global_object()); |
| 7490 LookupIterator it(global_object, name, LookupIterator::OWN); |
| 7491 if (CanInlineGlobalPropertyAccess(&it, access)) { |
| 7492 BuildCheckHeapObject(object); |
| 7493 Add<HCheckMaps>(object, maps); |
| 7494 if (access == LOAD) { |
| 7495 InlineGlobalPropertyLoad(&it, expr->id()); |
| 7496 return nullptr; |
| 7497 } else { |
| 7498 return InlineGlobalPropertyStore(&it, value, expr->id()); |
| 7499 } |
| 7500 } |
| 7501 } |
| 7502 } |
| 7503 |
| 7464 PropertyAccessInfo info(this, access, maps->first(), name); | 7504 PropertyAccessInfo info(this, access, maps->first(), name); |
| 7465 if (!info.CanAccessAsMonomorphic(maps)) { | 7505 if (!info.CanAccessAsMonomorphic(maps)) { |
| 7466 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id, | 7506 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id, |
| 7467 object, value, maps, name); | 7507 object, value, maps, name); |
| 7468 return NULL; | 7508 return NULL; |
| 7469 } | 7509 } |
| 7470 | 7510 |
| 7471 HValue* checked_object; | 7511 HValue* checked_object; |
| 7472 // AstType::Number() is only supported by polymorphic load/call handling. | 7512 // AstType::Number() is only supported by polymorphic load/call handling. |
| 7473 DCHECK(!info.IsNumberType()); | 7513 DCHECK(!info.IsNumberType()); |
| (...skipping 5521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12995 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13035 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 12996 } | 13036 } |
| 12997 | 13037 |
| 12998 #ifdef DEBUG | 13038 #ifdef DEBUG |
| 12999 graph_->Verify(false); // No full verify. | 13039 graph_->Verify(false); // No full verify. |
| 13000 #endif | 13040 #endif |
| 13001 } | 13041 } |
| 13002 | 13042 |
| 13003 } // namespace internal | 13043 } // namespace internal |
| 13004 } // namespace v8 | 13044 } // namespace v8 |
| OLD | NEW |