Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(233)

Side by Side Diff: src/hydrogen.cc

Issue 21065006: Replace HCheckPrototypeMaps by explicit map checks of constant values. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Prepare all HConstant js objects Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 4084 matching lines...) Expand 10 before | Expand all | Expand 10 after
4095 4095
4096 // Determines whether the given array or object literal boilerplate satisfies 4096 // Determines whether the given array or object literal boilerplate satisfies
4097 // all limits to be considered for fast deep-copying and computes the total 4097 // all limits to be considered for fast deep-copying and computes the total
4098 // size of all objects that are part of the graph. 4098 // size of all objects that are part of the graph.
4099 static bool IsFastLiteral(Handle<JSObject> boilerplate, 4099 static bool IsFastLiteral(Handle<JSObject> boilerplate,
4100 int max_depth, 4100 int max_depth,
4101 int* max_properties, 4101 int* max_properties,
4102 int* data_size, 4102 int* data_size,
4103 int* pointer_size) { 4103 int* pointer_size) {
4104 if (boilerplate->map()->is_deprecated()) { 4104 if (boilerplate->map()->is_deprecated()) {
4105 Handle<Object> result = 4105 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate);
4106 JSObject::TryMigrateInstance(boilerplate);
4107 if (result->IsSmi()) return false; 4106 if (result->IsSmi()) return false;
4108 } 4107 }
4109 4108
4110 ASSERT(max_depth >= 0 && *max_properties >= 0); 4109 ASSERT(max_depth >= 0 && *max_properties >= 0);
4111 if (max_depth == 0) return false; 4110 if (max_depth == 0) return false;
4112 4111
4113 Isolate* isolate = boilerplate->GetIsolate(); 4112 Isolate* isolate = boilerplate->GetIsolate();
4114 Handle<FixedArrayBase> elements(boilerplate->elements()); 4113 Handle<FixedArrayBase> elements(boilerplate->elements());
4115 if (elements->length() > 0 && 4114 if (elements->length() > 0 &&
4116 elements->map() != isolate->heap()->fixed_cow_array_map()) { 4115 elements->map() != isolate->heap()->fixed_cow_array_map()) {
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
4496 // We only need to check up to the preexisting property. 4495 // We only need to check up to the preexisting property.
4497 proto = proto_result.holder(); 4496 proto = proto_result.holder();
4498 } else { 4497 } else {
4499 // Otherwise, find the top prototype. 4498 // Otherwise, find the top prototype.
4500 while (proto->GetPrototype(isolate())->IsJSObject()) { 4499 while (proto->GetPrototype(isolate())->IsJSObject()) {
4501 proto = proto->GetPrototype(isolate()); 4500 proto = proto->GetPrototype(isolate());
4502 } 4501 }
4503 ASSERT(proto->GetPrototype(isolate())->IsNull()); 4502 ASSERT(proto->GetPrototype(isolate())->IsNull());
4504 } 4503 }
4505 ASSERT(proto->IsJSObject()); 4504 ASSERT(proto->IsJSObject());
4506 Add<HCheckPrototypeMaps>( 4505 BuildCheckPrototypeMaps(
4507 Handle<JSObject>(JSObject::cast(map->prototype())), 4506 Handle<JSObject>(JSObject::cast(map->prototype())),
4508 Handle<JSObject>(JSObject::cast(proto)), top_info()); 4507 Handle<JSObject>(JSObject::cast(proto)));
4509 } 4508 }
4510 4509
4511 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); 4510 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
4512 bool transition_to_field = lookup->IsTransitionToField(*map); 4511 bool transition_to_field = lookup->IsTransitionToField(*map);
4513 4512
4514 HStoreNamedField *instr; 4513 HStoreNamedField *instr;
4515 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { 4514 if (FLAG_track_double_fields && field_access.representation().IsDouble()) {
4516 HObjectAccess heap_number_access = 4515 HObjectAccess heap_number_access =
4517 field_access.WithRepresentation(Representation::Tagged()); 4516 field_access.WithRepresentation(Representation::Tagged());
4518 if (transition_to_field) { 4517 if (transition_to_field) {
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
4651 } 4650 }
4652 4651
4653 LookupInPrototypes(map, name, &lookup); 4652 LookupInPrototypes(map, name, &lookup);
4654 if (!lookup.IsField()) return NULL; 4653 if (!lookup.IsField()) return NULL;
4655 4654
4656 BuildCheckHeapObject(object); 4655 BuildCheckHeapObject(object);
4657 Add<HCheckMaps>(object, types); 4656 Add<HCheckMaps>(object, types);
4658 4657
4659 Handle<JSObject> holder(lookup.holder()); 4658 Handle<JSObject> holder(lookup.holder());
4660 Handle<Map> holder_map(holder->map()); 4659 Handle<Map> holder_map(holder->map());
4661 Add<HCheckPrototypeMaps>( 4660 BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder);
4662 Handle<JSObject>::cast(prototype), holder, top_info());
4663 HValue* holder_value = Add<HConstant>(holder); 4661 HValue* holder_value = Add<HConstant>(holder);
4664 return BuildLoadNamedField(holder_value, 4662 return BuildLoadNamedField(holder_value,
4665 HObjectAccess::ForField(holder_map, &lookup, name)); 4663 HObjectAccess::ForField(holder_map, &lookup, name));
4666 } 4664 }
4667 4665
4668 4666
4669 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( 4667 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
4670 Property* expr, 4668 Property* expr,
4671 HValue* object, 4669 HValue* object,
4672 SmallMapList* types, 4670 SmallMapList* types,
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after
5372 return New<HConstant>(constant); 5370 return New<HConstant>(constant);
5373 } 5371 }
5374 5372
5375 // Handle a load from a known field somewhere in the prototype chain. 5373 // Handle a load from a known field somewhere in the prototype chain.
5376 LookupInPrototypes(map, name, &lookup); 5374 LookupInPrototypes(map, name, &lookup);
5377 if (lookup.IsField()) { 5375 if (lookup.IsField()) {
5378 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5376 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5379 Handle<JSObject> holder(lookup.holder()); 5377 Handle<JSObject> holder(lookup.holder());
5380 Handle<Map> holder_map(holder->map()); 5378 Handle<Map> holder_map(holder->map());
5381 AddCheckMap(object, map); 5379 AddCheckMap(object, map);
5382 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); 5380 BuildCheckPrototypeMaps(prototype, holder);
5383 HValue* holder_value = Add<HConstant>(holder); 5381 HValue* holder_value = Add<HConstant>(holder);
5384 return BuildLoadNamedField(holder_value, 5382 return BuildLoadNamedField(holder_value,
5385 HObjectAccess::ForField(holder_map, &lookup, name)); 5383 HObjectAccess::ForField(holder_map, &lookup, name));
5386 } 5384 }
5387 5385
5388 // Handle a load of a constant function somewhere in the prototype chain. 5386 // Handle a load of a constant function somewhere in the prototype chain.
5389 if (lookup.IsConstant()) { 5387 if (lookup.IsConstant()) {
5390 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5388 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5391 Handle<JSObject> holder(lookup.holder()); 5389 Handle<JSObject> holder(lookup.holder());
5392 Handle<Map> holder_map(holder->map()); 5390 Handle<Map> holder_map(holder->map());
5393 AddCheckMap(object, map); 5391 AddCheckMap(object, map);
5394 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); 5392 BuildCheckPrototypeMaps(prototype, holder);
5395 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); 5393 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate());
5396 return New<HConstant>(constant); 5394 return New<HConstant>(constant);
5397 } 5395 }
5398 5396
5399 // No luck, do a generic load. 5397 // No luck, do a generic load.
5400 return BuildLoadNamedGeneric(object, name, expr); 5398 return BuildLoadNamedGeneric(object, name, expr);
5401 } 5399 }
5402 5400
5403 5401
5404 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 5402 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
(...skipping 15 matching lines...) Expand all
5420 if (dependency) { 5418 if (dependency) {
5421 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 5419 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
5422 } 5420 }
5423 5421
5424 // Loads from a "stock" fast holey double arrays can elide the hole check. 5422 // Loads from a "stock" fast holey double arrays can elide the hole check.
5425 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; 5423 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
5426 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && 5424 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
5427 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { 5425 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
5428 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); 5426 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
5429 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); 5427 Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
5430 Add<HCheckPrototypeMaps>(prototype, object_prototype, top_info()); 5428 BuildCheckPrototypeMaps(prototype, object_prototype);
5431 load_mode = ALLOW_RETURN_HOLE; 5429 load_mode = ALLOW_RETURN_HOLE;
5432 graph()->MarkDependsOnEmptyArrayProtoElements(); 5430 graph()->MarkDependsOnEmptyArrayProtoElements();
5433 } 5431 }
5434 5432
5435 return BuildUncheckedMonomorphicElementAccess( 5433 return BuildUncheckedMonomorphicElementAccess(
5436 object, key, val, 5434 object, key, val,
5437 mapcheck, map->instance_type() == JS_ARRAY_TYPE, 5435 mapcheck, map->instance_type() == JS_ARRAY_TYPE,
5438 map->elements_kind(), is_store, load_mode, store_mode); 5436 map->elements_kind(), is_store, load_mode, store_mode);
5439 } 5437 }
5440 5438
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after
5865 Drop(1); 5863 Drop(1);
5866 } 5864 }
5867 } 5865 }
5868 return ast_context()->ReturnValue(load); 5866 return ast_context()->ReturnValue(load);
5869 } 5867 }
5870 instr->set_position(expr->position()); 5868 instr->set_position(expr->position());
5871 return ast_context()->ReturnInstruction(instr, expr->id()); 5869 return ast_context()->ReturnInstruction(instr, expr->id());
5872 } 5870 }
5873 5871
5874 5872
5873 void HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
5874 CompilationInfo* info) {
5875 HConstant* constant_value = New<HConstant>(constant);
5876
5877 if (constant->map()->CanOmitMapChecks()) {
5878 constant->map()->AddDependentCompilationInfo(
5879 DependentCode::kPrototypeCheckGroup, info);
5880 return;
5881 }
5882
5883 AddInstruction(constant_value);
5884 HCheckMaps* check =
5885 Add<HCheckMaps>(constant_value, handle(constant->map()), info);
5886 check->ClearGVNFlag(kDependsOnElementsKind);
5887 }
5888
5889
5890 void HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
5891 Handle<JSObject> holder) {
5892 BuildConstantMapCheck(prototype, top_info());
5893 while (!prototype.is_identical_to(holder)) {
5894 prototype = handle(JSObject::cast(prototype->GetPrototype()));
5895 BuildConstantMapCheck(prototype, top_info());
5896 }
5897 }
5898
5899
5875 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, 5900 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
5876 Handle<Map> receiver_map) { 5901 Handle<Map> receiver_map) {
5877 if (!holder.is_null()) { 5902 if (!holder.is_null()) {
5878 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); 5903 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
5879 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); 5904 BuildCheckPrototypeMaps(prototype, holder);
5880 } 5905 }
5881 } 5906 }
5882 5907
5883 5908
5884 void HOptimizedGraphBuilder::AddCheckConstantFunction( 5909 void HOptimizedGraphBuilder::AddCheckConstantFunction(
5885 Handle<JSObject> holder, 5910 Handle<JSObject> holder,
5886 HValue* receiver, 5911 HValue* receiver,
5887 Handle<Map> receiver_map) { 5912 Handle<Map> receiver_map) {
5888 // Constant functions have the nice property that the map will change if they 5913 // Constant functions have the nice property that the map will change if they
5889 // are overwritten. Therefore it is enough to check the map of the holder and 5914 // are overwritten. Therefore it is enough to check the map of the holder and
(...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after
6610 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 6635 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
6611 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 6636 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
6612 switch (id) { 6637 switch (id) {
6613 case kStringCharCodeAt: 6638 case kStringCharCodeAt:
6614 case kStringCharAt: 6639 case kStringCharAt:
6615 if (argument_count == 2 && check_type == STRING_CHECK) { 6640 if (argument_count == 2 && check_type == STRING_CHECK) {
6616 HValue* index = Pop(); 6641 HValue* index = Pop();
6617 HValue* string = Pop(); 6642 HValue* string = Pop();
6618 HValue* context = environment()->context(); 6643 HValue* context = environment()->context();
6619 ASSERT(!expr->holder().is_null()); 6644 ASSERT(!expr->holder().is_null());
6620 Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck( 6645 BuildCheckPrototypeMaps(Call::GetPrototypeForPrimitiveCheck(
6621 STRING_CHECK, expr->holder()->GetIsolate()), 6646 STRING_CHECK, expr->holder()->GetIsolate()),
6622 expr->holder(), top_info()); 6647 expr->holder());
6623 HInstruction* char_code = 6648 HInstruction* char_code =
6624 BuildStringCharCodeAt(string, index); 6649 BuildStringCharCodeAt(string, index);
6625 if (id == kStringCharCodeAt) { 6650 if (id == kStringCharCodeAt) {
6626 ast_context()->ReturnInstruction(char_code, expr->id()); 6651 ast_context()->ReturnInstruction(char_code, expr->id());
6627 return true; 6652 return true;
6628 } 6653 }
6629 AddInstruction(char_code); 6654 AddInstruction(char_code);
6630 HInstruction* result = 6655 HInstruction* result =
6631 HStringCharFromCode::New(zone(), context, char_code); 6656 HStringCharFromCode::New(zone(), context, char_code);
6632 ast_context()->ReturnInstruction(result, expr->id()); 6657 ast_context()->ReturnInstruction(result, expr->id());
(...skipping 3132 matching lines...) Expand 10 before | Expand all | Expand 10 after
9765 if (ShouldProduceTraceOutput()) { 9790 if (ShouldProduceTraceOutput()) {
9766 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9791 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9767 } 9792 }
9768 9793
9769 #ifdef DEBUG 9794 #ifdef DEBUG
9770 graph_->Verify(false); // No full verify. 9795 graph_->Verify(false); // No full verify.
9771 #endif 9796 #endif
9772 } 9797 }
9773 9798
9774 } } // namespace v8::internal 9799 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698