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

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: 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 3885 matching lines...) Expand 10 before | Expand all | Expand 10 after
3896 ASSERT(var->IsContextSlot()); 3896 ASSERT(var->IsContextSlot());
3897 HValue* context = environment()->context(); 3897 HValue* context = environment()->context();
3898 int length = current_info()->scope()->ContextChainLength(var->scope()); 3898 int length = current_info()->scope()->ContextChainLength(var->scope());
3899 while (length-- > 0) { 3899 while (length-- > 0) {
3900 context = Add<HOuterContext>(context); 3900 context = Add<HOuterContext>(context);
3901 } 3901 }
3902 return context; 3902 return context;
3903 } 3903 }
3904 3904
3905 3905
3906 static void PrepareConstant(Handle<Object> object) {
3907 if (!object->IsJSObject()) return;
3908 Handle<JSObject> js_object = Handle<JSObject>::cast(object);
3909 if (!js_object->map()->is_deprecated()) return;
3910 JSObject::TryMigrateInstance(js_object);
3911 }
3912
3913
3906 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 3914 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
3907 ASSERT(!HasStackOverflow()); 3915 ASSERT(!HasStackOverflow());
3908 ASSERT(current_block() != NULL); 3916 ASSERT(current_block() != NULL);
3909 ASSERT(current_block()->HasPredecessor()); 3917 ASSERT(current_block()->HasPredecessor());
3910 Variable* variable = expr->var(); 3918 Variable* variable = expr->var();
3911 switch (variable->location()) { 3919 switch (variable->location()) {
3912 case Variable::UNALLOCATED: { 3920 case Variable::UNALLOCATED: {
3913 if (IsLexicalVariableMode(variable->mode())) { 3921 if (IsLexicalVariableMode(variable->mode())) {
3914 // TODO(rossberg): should this be an ASSERT? 3922 // TODO(rossberg): should this be an ASSERT?
3915 return Bailout("reference to global lexical variable"); 3923 return Bailout("reference to global lexical variable");
(...skipping 19 matching lines...) Expand all
3935 if (type == kUseCell) { 3943 if (type == kUseCell) {
3936 Handle<GlobalObject> global(current_info()->global_object()); 3944 Handle<GlobalObject> global(current_info()->global_object());
3937 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); 3945 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
3938 if (cell->type()->IsConstant()) { 3946 if (cell->type()->IsConstant()) {
3939 cell->AddDependentCompilationInfo(top_info()); 3947 cell->AddDependentCompilationInfo(top_info());
3940 Handle<Object> constant_object = cell->type()->AsConstant(); 3948 Handle<Object> constant_object = cell->type()->AsConstant();
3941 if (constant_object->IsConsString()) { 3949 if (constant_object->IsConsString()) {
3942 constant_object = 3950 constant_object =
3943 FlattenGetString(Handle<String>::cast(constant_object)); 3951 FlattenGetString(Handle<String>::cast(constant_object));
3944 } 3952 }
3953 PrepareConstant(constant_object);
3945 HConstant* constant = New<HConstant>(constant_object); 3954 HConstant* constant = New<HConstant>(constant_object);
danno 2013/08/02 08:52:11 Maybe you should just put PrepareConstant into the
Toon Verwaest 2013/08/02 09:06:11 Done.
3946 return ast_context()->ReturnInstruction(constant, expr->id()); 3955 return ast_context()->ReturnInstruction(constant, expr->id());
3947 } else { 3956 } else {
3948 HLoadGlobalCell* instr = 3957 HLoadGlobalCell* instr =
3949 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); 3958 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
3950 return ast_context()->ReturnInstruction(instr, expr->id()); 3959 return ast_context()->ReturnInstruction(instr, expr->id());
3951 } 3960 }
3952 } else { 3961 } else {
3953 HValue* context = environment()->context(); 3962 HValue* context = environment()->context();
3954 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 3963 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
3955 AddInstruction(global_object); 3964 AddInstruction(global_object);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
4095 4104
4096 // Determines whether the given array or object literal boilerplate satisfies 4105 // Determines whether the given array or object literal boilerplate satisfies
4097 // all limits to be considered for fast deep-copying and computes the total 4106 // all limits to be considered for fast deep-copying and computes the total
4098 // size of all objects that are part of the graph. 4107 // size of all objects that are part of the graph.
4099 static bool IsFastLiteral(Handle<JSObject> boilerplate, 4108 static bool IsFastLiteral(Handle<JSObject> boilerplate,
4100 int max_depth, 4109 int max_depth,
4101 int* max_properties, 4110 int* max_properties,
4102 int* data_size, 4111 int* data_size,
4103 int* pointer_size) { 4112 int* pointer_size) {
4104 if (boilerplate->map()->is_deprecated()) { 4113 if (boilerplate->map()->is_deprecated()) {
4105 Handle<Object> result = 4114 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate);
4106 JSObject::TryMigrateInstance(boilerplate);
4107 if (result->IsSmi()) return false; 4115 if (result->IsSmi()) return false;
4108 } 4116 }
4109 4117
4110 ASSERT(max_depth >= 0 && *max_properties >= 0); 4118 ASSERT(max_depth >= 0 && *max_properties >= 0);
4111 if (max_depth == 0) return false; 4119 if (max_depth == 0) return false;
4112 4120
4113 Isolate* isolate = boilerplate->GetIsolate(); 4121 Isolate* isolate = boilerplate->GetIsolate();
4114 Handle<FixedArrayBase> elements(boilerplate->elements()); 4122 Handle<FixedArrayBase> elements(boilerplate->elements());
4115 if (elements->length() > 0 && 4123 if (elements->length() > 0 &&
4116 elements->map() != isolate->heap()->fixed_cow_array_map()) { 4124 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. 4504 // We only need to check up to the preexisting property.
4497 proto = proto_result.holder(); 4505 proto = proto_result.holder();
4498 } else { 4506 } else {
4499 // Otherwise, find the top prototype. 4507 // Otherwise, find the top prototype.
4500 while (proto->GetPrototype(isolate())->IsJSObject()) { 4508 while (proto->GetPrototype(isolate())->IsJSObject()) {
4501 proto = proto->GetPrototype(isolate()); 4509 proto = proto->GetPrototype(isolate());
4502 } 4510 }
4503 ASSERT(proto->GetPrototype(isolate())->IsNull()); 4511 ASSERT(proto->GetPrototype(isolate())->IsNull());
4504 } 4512 }
4505 ASSERT(proto->IsJSObject()); 4513 ASSERT(proto->IsJSObject());
4506 Add<HCheckPrototypeMaps>( 4514 BuildCheckPrototypeMaps(
4507 Handle<JSObject>(JSObject::cast(map->prototype())), 4515 Handle<JSObject>(JSObject::cast(map->prototype())),
4508 Handle<JSObject>(JSObject::cast(proto)), top_info()); 4516 Handle<JSObject>(JSObject::cast(proto)));
4509 } 4517 }
4510 4518
4511 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); 4519 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
4512 bool transition_to_field = lookup->IsTransitionToField(*map); 4520 bool transition_to_field = lookup->IsTransitionToField(*map);
4513 4521
4514 HStoreNamedField *instr; 4522 HStoreNamedField *instr;
4515 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { 4523 if (FLAG_track_double_fields && field_access.representation().IsDouble()) {
4516 HObjectAccess heap_number_access = 4524 HObjectAccess heap_number_access =
4517 field_access.WithRepresentation(Representation::Tagged()); 4525 field_access.WithRepresentation(Representation::Tagged());
4518 if (transition_to_field) { 4526 if (transition_to_field) {
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
4651 } 4659 }
4652 4660
4653 LookupInPrototypes(map, name, &lookup); 4661 LookupInPrototypes(map, name, &lookup);
4654 if (!lookup.IsField()) return NULL; 4662 if (!lookup.IsField()) return NULL;
4655 4663
4656 BuildCheckHeapObject(object); 4664 BuildCheckHeapObject(object);
4657 Add<HCheckMaps>(object, types); 4665 Add<HCheckMaps>(object, types);
4658 4666
4659 Handle<JSObject> holder(lookup.holder()); 4667 Handle<JSObject> holder(lookup.holder());
4660 Handle<Map> holder_map(holder->map()); 4668 Handle<Map> holder_map(holder->map());
4661 Add<HCheckPrototypeMaps>( 4669 BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder);
4662 Handle<JSObject>::cast(prototype), holder, top_info());
4663 HValue* holder_value = Add<HConstant>(holder); 4670 HValue* holder_value = Add<HConstant>(holder);
4664 return BuildLoadNamedField(holder_value, 4671 return BuildLoadNamedField(holder_value,
4665 HObjectAccess::ForField(holder_map, &lookup, name)); 4672 HObjectAccess::ForField(holder_map, &lookup, name));
4666 } 4673 }
4667 4674
4668 4675
4669 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( 4676 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
4670 Property* expr, 4677 Property* expr,
4671 HValue* object, 4678 HValue* object,
4672 SmallMapList* types, 4679 SmallMapList* types,
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after
5372 return New<HConstant>(constant); 5379 return New<HConstant>(constant);
5373 } 5380 }
5374 5381
5375 // Handle a load from a known field somewhere in the prototype chain. 5382 // Handle a load from a known field somewhere in the prototype chain.
5376 LookupInPrototypes(map, name, &lookup); 5383 LookupInPrototypes(map, name, &lookup);
5377 if (lookup.IsField()) { 5384 if (lookup.IsField()) {
5378 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5385 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5379 Handle<JSObject> holder(lookup.holder()); 5386 Handle<JSObject> holder(lookup.holder());
5380 Handle<Map> holder_map(holder->map()); 5387 Handle<Map> holder_map(holder->map());
5381 AddCheckMap(object, map); 5388 AddCheckMap(object, map);
5382 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); 5389 BuildCheckPrototypeMaps(prototype, holder);
5383 HValue* holder_value = Add<HConstant>(holder); 5390 HValue* holder_value = Add<HConstant>(holder);
5384 return BuildLoadNamedField(holder_value, 5391 return BuildLoadNamedField(holder_value,
5385 HObjectAccess::ForField(holder_map, &lookup, name)); 5392 HObjectAccess::ForField(holder_map, &lookup, name));
5386 } 5393 }
5387 5394
5388 // Handle a load of a constant function somewhere in the prototype chain. 5395 // Handle a load of a constant function somewhere in the prototype chain.
5389 if (lookup.IsConstant()) { 5396 if (lookup.IsConstant()) {
5390 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5397 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5391 Handle<JSObject> holder(lookup.holder()); 5398 Handle<JSObject> holder(lookup.holder());
5392 Handle<Map> holder_map(holder->map()); 5399 Handle<Map> holder_map(holder->map());
5393 AddCheckMap(object, map); 5400 AddCheckMap(object, map);
5394 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); 5401 BuildCheckPrototypeMaps(prototype, holder);
5395 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); 5402 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate());
5396 return New<HConstant>(constant); 5403 return New<HConstant>(constant);
5397 } 5404 }
5398 5405
5399 // No luck, do a generic load. 5406 // No luck, do a generic load.
5400 return BuildLoadNamedGeneric(object, name, expr); 5407 return BuildLoadNamedGeneric(object, name, expr);
5401 } 5408 }
5402 5409
5403 5410
5404 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 5411 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
(...skipping 15 matching lines...) Expand all
5420 if (dependency) { 5427 if (dependency) {
5421 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 5428 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
5422 } 5429 }
5423 5430
5424 // Loads from a "stock" fast holey double arrays can elide the hole check. 5431 // Loads from a "stock" fast holey double arrays can elide the hole check.
5425 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; 5432 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
5426 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && 5433 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
5427 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { 5434 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
5428 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); 5435 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
5429 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); 5436 Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
5430 Add<HCheckPrototypeMaps>(prototype, object_prototype, top_info()); 5437 BuildCheckPrototypeMaps(prototype, object_prototype);
5431 load_mode = ALLOW_RETURN_HOLE; 5438 load_mode = ALLOW_RETURN_HOLE;
5432 graph()->MarkDependsOnEmptyArrayProtoElements(); 5439 graph()->MarkDependsOnEmptyArrayProtoElements();
5433 } 5440 }
5434 5441
5435 return BuildUncheckedMonomorphicElementAccess( 5442 return BuildUncheckedMonomorphicElementAccess(
5436 object, key, val, 5443 object, key, val,
5437 mapcheck, map->instance_type() == JS_ARRAY_TYPE, 5444 mapcheck, map->instance_type() == JS_ARRAY_TYPE,
5438 map->elements_kind(), is_store, load_mode, store_mode); 5445 map->elements_kind(), is_store, load_mode, store_mode);
5439 } 5446 }
5440 5447
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after
5865 Drop(1); 5872 Drop(1);
5866 } 5873 }
5867 } 5874 }
5868 return ast_context()->ReturnValue(load); 5875 return ast_context()->ReturnValue(load);
5869 } 5876 }
5870 instr->set_position(expr->position()); 5877 instr->set_position(expr->position());
5871 return ast_context()->ReturnInstruction(instr, expr->id()); 5878 return ast_context()->ReturnInstruction(instr, expr->id());
5872 } 5879 }
5873 5880
5874 5881
5882 void HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
5883 CompilationInfo* info) {
5884 PrepareConstant(constant);
5885
5886 if (constant->map()->CanOmitMapChecks()) {
5887 constant->map()->AddDependentCompilationInfo(
5888 DependentCode::kPrototypeCheckGroup, info);
5889 return;
5890 }
5891
5892 HConstant* constant_value = Add<HConstant>(constant);
5893 HCheckMaps* check =
5894 Add<HCheckMaps>(constant_value, handle(constant->map()), info);
5895 check->ClearGVNFlag(kDependsOnElementsKind);
5896 }
5897
5898
5899 void HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
5900 Handle<JSObject> holder) {
5901 BuildConstantMapCheck(prototype, top_info());
5902 while (!prototype.is_identical_to(holder)) {
5903 prototype = handle(JSObject::cast(prototype->GetPrototype()));
5904 BuildConstantMapCheck(prototype, top_info());
5905 }
5906 }
5907
5908
5875 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, 5909 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
5876 Handle<Map> receiver_map) { 5910 Handle<Map> receiver_map) {
5877 if (!holder.is_null()) { 5911 if (!holder.is_null()) {
5878 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); 5912 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
5879 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); 5913 BuildCheckPrototypeMaps(prototype, holder);
5880 } 5914 }
5881 } 5915 }
5882 5916
5883 5917
5884 void HOptimizedGraphBuilder::AddCheckConstantFunction( 5918 void HOptimizedGraphBuilder::AddCheckConstantFunction(
5885 Handle<JSObject> holder, 5919 Handle<JSObject> holder,
5886 HValue* receiver, 5920 HValue* receiver,
5887 Handle<Map> receiver_map) { 5921 Handle<Map> receiver_map) {
5888 // Constant functions have the nice property that the map will change if they 5922 // 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 5923 // 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(); 6644 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
6611 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 6645 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
6612 switch (id) { 6646 switch (id) {
6613 case kStringCharCodeAt: 6647 case kStringCharCodeAt:
6614 case kStringCharAt: 6648 case kStringCharAt:
6615 if (argument_count == 2 && check_type == STRING_CHECK) { 6649 if (argument_count == 2 && check_type == STRING_CHECK) {
6616 HValue* index = Pop(); 6650 HValue* index = Pop();
6617 HValue* string = Pop(); 6651 HValue* string = Pop();
6618 HValue* context = environment()->context(); 6652 HValue* context = environment()->context();
6619 ASSERT(!expr->holder().is_null()); 6653 ASSERT(!expr->holder().is_null());
6620 Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck( 6654 BuildCheckPrototypeMaps(Call::GetPrototypeForPrimitiveCheck(
6621 STRING_CHECK, expr->holder()->GetIsolate()), 6655 STRING_CHECK, expr->holder()->GetIsolate()),
6622 expr->holder(), top_info()); 6656 expr->holder());
6623 HInstruction* char_code = 6657 HInstruction* char_code =
6624 BuildStringCharCodeAt(string, index); 6658 BuildStringCharCodeAt(string, index);
6625 if (id == kStringCharCodeAt) { 6659 if (id == kStringCharCodeAt) {
6626 ast_context()->ReturnInstruction(char_code, expr->id()); 6660 ast_context()->ReturnInstruction(char_code, expr->id());
6627 return true; 6661 return true;
6628 } 6662 }
6629 AddInstruction(char_code); 6663 AddInstruction(char_code);
6630 HInstruction* result = 6664 HInstruction* result =
6631 HStringCharFromCode::New(zone(), context, char_code); 6665 HStringCharFromCode::New(zone(), context, char_code);
6632 ast_context()->ReturnInstruction(result, expr->id()); 6666 ast_context()->ReturnInstruction(result, expr->id());
(...skipping 3132 matching lines...) Expand 10 before | Expand all | Expand 10 after
9765 if (ShouldProduceTraceOutput()) { 9799 if (ShouldProduceTraceOutput()) {
9766 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9800 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9767 } 9801 }
9768 9802
9769 #ifdef DEBUG 9803 #ifdef DEBUG
9770 graph_->Verify(false); // No full verify. 9804 graph_->Verify(false); // No full verify.
9771 #endif 9805 #endif
9772 } 9806 }
9773 9807
9774 } } // namespace v8::internal 9808 } } // 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