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

Side by Side Diff: src/objects.cc

Issue 2598543003: [runtime][ic] Constant field tracking support. (Closed)
Patch Set: Addressing comments Created 3 years, 10 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
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.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 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 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/objects.h" 5 #include "src/objects.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <iomanip> 8 #include <iomanip>
9 #include <memory> 9 #include <memory>
10 #include <sstream> 10 #include <sstream>
(...skipping 3350 matching lines...) Expand 10 before | Expand all | Expand 10 after
3361 if (value->IsWeakCell()) { 3361 if (value->IsWeakCell()) {
3362 if (WeakCell::cast(value)->cleared()) return FieldType::None(); 3362 if (WeakCell::cast(value)->cleared()) return FieldType::None();
3363 value = WeakCell::cast(value)->value(); 3363 value = WeakCell::cast(value)->value();
3364 } 3364 }
3365 return FieldType::cast(value); 3365 return FieldType::cast(value);
3366 } 3366 }
3367 3367
3368 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, Handle<Name> name, 3368 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, Handle<Name> name,
3369 Handle<FieldType> type, 3369 Handle<FieldType> type,
3370 PropertyAttributes attributes, 3370 PropertyAttributes attributes,
3371 PropertyConstness constness,
3371 Representation representation, 3372 Representation representation,
3372 TransitionFlag flag) { 3373 TransitionFlag flag) {
3373 DCHECK(DescriptorArray::kNotFound == 3374 DCHECK(DescriptorArray::kNotFound ==
3374 map->instance_descriptors()->Search( 3375 map->instance_descriptors()->Search(
3375 *name, map->NumberOfOwnDescriptors())); 3376 *name, map->NumberOfOwnDescriptors()));
3376 3377
3377 // Ensure the descriptor array does not get too big. 3378 // Ensure the descriptor array does not get too big.
3378 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) { 3379 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
3379 return MaybeHandle<Map>(); 3380 return MaybeHandle<Map>();
3380 } 3381 }
3381 3382
3382 Isolate* isolate = map->GetIsolate(); 3383 Isolate* isolate = map->GetIsolate();
3383 3384
3384 // Compute the new index for new field. 3385 // Compute the new index for new field.
3385 int index = map->NextFreePropertyIndex(); 3386 int index = map->NextFreePropertyIndex();
3386 3387
3387 if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) { 3388 if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
3388 representation = Representation::Tagged(); 3389 representation = Representation::Tagged();
3389 type = FieldType::Any(isolate); 3390 type = FieldType::Any(isolate);
3390 } 3391 }
3391 3392
3392 Handle<Object> wrapped_type(WrapFieldType(type)); 3393 Handle<Object> wrapped_type(WrapFieldType(type));
3393 3394
3394 Descriptor d = Descriptor::DataField(name, index, attributes, kMutable, 3395 DCHECK_IMPLIES(!FLAG_track_constant_fields, constness == kMutable);
3396 Descriptor d = Descriptor::DataField(name, index, attributes, constness,
3395 representation, wrapped_type); 3397 representation, wrapped_type);
3396 Handle<Map> new_map = Map::CopyAddDescriptor(map, &d, flag); 3398 Handle<Map> new_map = Map::CopyAddDescriptor(map, &d, flag);
3397 int unused_property_fields = new_map->unused_property_fields() - 1; 3399 int unused_property_fields = new_map->unused_property_fields() - 1;
3398 if (unused_property_fields < 0) { 3400 if (unused_property_fields < 0) {
3399 unused_property_fields += JSObject::kFieldsAdded; 3401 unused_property_fields += JSObject::kFieldsAdded;
3400 } 3402 }
3401 new_map->set_unused_property_fields(unused_property_fields); 3403 new_map->set_unused_property_fields(unused_property_fields);
3402 return new_map; 3404 return new_map;
3403 } 3405 }
3404 3406
3405 3407
3406 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map, 3408 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
3407 Handle<Name> name, 3409 Handle<Name> name,
3408 Handle<Object> constant, 3410 Handle<Object> constant,
3409 PropertyAttributes attributes, 3411 PropertyAttributes attributes,
3410 TransitionFlag flag) { 3412 TransitionFlag flag) {
3411 // Ensure the descriptor array does not get too big. 3413 // Ensure the descriptor array does not get too big.
3412 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) { 3414 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
3413 return MaybeHandle<Map>(); 3415 return MaybeHandle<Map>();
3414 } 3416 }
3415 3417
3416 // Allocate new instance descriptors with (name, constant) added. 3418 if (FLAG_track_constant_fields) {
3417 Descriptor d = Descriptor::DataConstant(name, constant, attributes); 3419 Isolate* isolate = map->GetIsolate();
3418 return Map::CopyAddDescriptor(map, &d, flag); 3420 Representation representation = constant->OptimalRepresentation();
3421 Handle<FieldType> type = constant->OptimalType(isolate, representation);
3422 return CopyWithField(map, name, type, attributes, kConst, representation,
3423 flag);
3424 } else {
3425 // Allocate new instance descriptors with (name, constant) added.
3426 Descriptor d = Descriptor::DataConstant(name, 0, constant, attributes);
3427 Handle<Map> new_map = Map::CopyAddDescriptor(map, &d, flag);
3428 return new_map;
3429 }
3419 } 3430 }
3420 3431
3421 const char* Representation::Mnemonic() const { 3432 const char* Representation::Mnemonic() const {
3422 switch (kind_) { 3433 switch (kind_) {
3423 case kNone: return "v"; 3434 case kNone: return "v";
3424 case kTagged: return "t"; 3435 case kTagged: return "t";
3425 case kSmi: return "s"; 3436 case kSmi: return "s";
3426 case kDouble: return "d"; 3437 case kDouble: return "d";
3427 case kInteger32: return "i"; 3438 case kInteger32: return "i";
3428 case kHeapObject: return "h"; 3439 case kHeapObject: return "h";
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
3916 return result; 3927 return result;
3917 } 3928 }
3918 3929
3919 void DescriptorArray::GeneralizeAllFields() { 3930 void DescriptorArray::GeneralizeAllFields() {
3920 int length = number_of_descriptors(); 3931 int length = number_of_descriptors();
3921 for (int i = 0; i < length; i++) { 3932 for (int i = 0; i < length; i++) {
3922 PropertyDetails details = GetDetails(i); 3933 PropertyDetails details = GetDetails(i);
3923 details = details.CopyWithRepresentation(Representation::Tagged()); 3934 details = details.CopyWithRepresentation(Representation::Tagged());
3924 if (details.location() == kField) { 3935 if (details.location() == kField) {
3925 DCHECK_EQ(kData, details.kind()); 3936 DCHECK_EQ(kData, details.kind());
3937 details = details.CopyWithConstness(kMutable);
3926 SetValue(i, FieldType::Any()); 3938 SetValue(i, FieldType::Any());
3927 } 3939 }
3928 set(ToDetailsIndex(i), details.AsSmi()); 3940 set(ToDetailsIndex(i), details.AsSmi());
3929 } 3941 }
3930 } 3942 }
3931 3943
3932 Handle<Map> Map::CopyGeneralizeAllFields(Handle<Map> map, 3944 Handle<Map> Map::CopyGeneralizeAllFields(Handle<Map> map,
3933 ElementsKind elements_kind, 3945 ElementsKind elements_kind,
3934 int modify_index, PropertyKind kind, 3946 int modify_index, PropertyKind kind,
3935 PropertyAttributes attributes, 3947 PropertyAttributes attributes,
3936 const char* reason) { 3948 const char* reason) {
3937 Isolate* isolate = map->GetIsolate(); 3949 Isolate* isolate = map->GetIsolate();
3938 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate); 3950 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
3939 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 3951 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
3940 Handle<DescriptorArray> descriptors = 3952 Handle<DescriptorArray> descriptors =
3941 DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors); 3953 DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
3942 descriptors->GeneralizeAllFields(); 3954 descriptors->GeneralizeAllFields();
3943 3955
3944 Handle<LayoutDescriptor> new_layout_descriptor( 3956 Handle<LayoutDescriptor> new_layout_descriptor(
3945 LayoutDescriptor::FastPointerLayout(), isolate); 3957 LayoutDescriptor::FastPointerLayout(), isolate);
3946 Handle<Map> new_map = CopyReplaceDescriptors( 3958 Handle<Map> new_map = CopyReplaceDescriptors(
3947 map, descriptors, new_layout_descriptor, OMIT_TRANSITION, 3959 map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
3948 MaybeHandle<Name>(), reason, SPECIAL_TRANSITION); 3960 MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
3949 3961
3950 // Unless the instance is being migrated, ensure that modify_index is a field. 3962 // Unless the instance is being migrated, ensure that modify_index is a field.
3951 if (modify_index >= 0) { 3963 if (modify_index >= 0) {
3952 PropertyDetails details = descriptors->GetDetails(modify_index); 3964 PropertyDetails details = descriptors->GetDetails(modify_index);
3953 if (details.location() != kField || details.attributes() != attributes) { 3965 if (details.constness() != kMutable || details.location() != kField ||
3966 details.attributes() != attributes) {
3954 int field_index = details.location() == kField 3967 int field_index = details.location() == kField
3955 ? details.field_index() 3968 ? details.field_index()
3956 : new_map->NumberOfFields(); 3969 : new_map->NumberOfFields();
3957 Descriptor d = Descriptor::DataField( 3970 Descriptor d = Descriptor::DataField(
3958 handle(descriptors->GetKey(modify_index), isolate), field_index, 3971 handle(descriptors->GetKey(modify_index), isolate), field_index,
3959 attributes, Representation::Tagged()); 3972 attributes, Representation::Tagged());
3960 descriptors->Replace(modify_index, &d); 3973 descriptors->Replace(modify_index, &d);
3961 if (details.location() != kField) { 3974 if (details.location() != kField) {
3962 int unused_property_fields = new_map->unused_property_fields() - 1; 3975 int unused_property_fields = new_map->unused_property_fields() - 1;
3963 if (unused_property_fields < 0) { 3976 if (unused_property_fields < 0) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
4052 while (true) { 4065 while (true) {
4053 Object* back = result->GetBackPointer(); 4066 Object* back = result->GetBackPointer();
4054 if (back->IsUndefined(isolate)) break; 4067 if (back->IsUndefined(isolate)) break;
4055 Map* parent = Map::cast(back); 4068 Map* parent = Map::cast(back);
4056 if (parent->NumberOfOwnDescriptors() <= descriptor) break; 4069 if (parent->NumberOfOwnDescriptors() <= descriptor) break;
4057 result = parent; 4070 result = parent;
4058 } 4071 }
4059 return result; 4072 return result;
4060 } 4073 }
4061 4074
4062
4063 void Map::UpdateFieldType(int descriptor, Handle<Name> name, 4075 void Map::UpdateFieldType(int descriptor, Handle<Name> name,
4076 PropertyConstness new_constness,
4064 Representation new_representation, 4077 Representation new_representation,
4065 Handle<Object> new_wrapped_type) { 4078 Handle<Object> new_wrapped_type) {
4066 DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell()); 4079 DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell());
4067 // We store raw pointers in the queue, so no allocations are allowed. 4080 // We store raw pointers in the queue, so no allocations are allowed.
4068 DisallowHeapAllocation no_allocation; 4081 DisallowHeapAllocation no_allocation;
4069 PropertyDetails details = instance_descriptors()->GetDetails(descriptor); 4082 PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
4070 if (details.location() != kField) return; 4083 if (details.location() != kField) return;
4071 DCHECK_EQ(kData, details.kind()); 4084 DCHECK_EQ(kData, details.kind());
4072 4085
4073 Zone zone(GetIsolate()->allocator(), ZONE_NAME); 4086 Zone zone(GetIsolate()->allocator(), ZONE_NAME);
4074 ZoneQueue<Map*> backlog(&zone); 4087 ZoneQueue<Map*> backlog(&zone);
4075 backlog.push(this); 4088 backlog.push(this);
4076 4089
4077 while (!backlog.empty()) { 4090 while (!backlog.empty()) {
4078 Map* current = backlog.front(); 4091 Map* current = backlog.front();
4079 backlog.pop(); 4092 backlog.pop();
4080 4093
4081 Object* transitions = current->raw_transitions(); 4094 Object* transitions = current->raw_transitions();
4082 int num_transitions = TransitionArray::NumberOfTransitions(transitions); 4095 int num_transitions = TransitionArray::NumberOfTransitions(transitions);
4083 for (int i = 0; i < num_transitions; ++i) { 4096 for (int i = 0; i < num_transitions; ++i) {
4084 Map* target = TransitionArray::GetTarget(transitions, i); 4097 Map* target = TransitionArray::GetTarget(transitions, i);
4085 backlog.push(target); 4098 backlog.push(target);
4086 } 4099 }
4087 DescriptorArray* descriptors = current->instance_descriptors(); 4100 DescriptorArray* descriptors = current->instance_descriptors();
4088 PropertyDetails details = descriptors->GetDetails(descriptor); 4101 PropertyDetails details = descriptors->GetDetails(descriptor);
4089 4102
4103 // Currently constness change implies map change.
4104 DCHECK_EQ(new_constness, details.constness());
4105
4090 // It is allowed to change representation here only from None to something. 4106 // It is allowed to change representation here only from None to something.
4091 DCHECK(details.representation().Equals(new_representation) || 4107 DCHECK(details.representation().Equals(new_representation) ||
4092 details.representation().IsNone()); 4108 details.representation().IsNone());
4093 4109
4094 // Skip if already updated the shared descriptor. 4110 // Skip if already updated the shared descriptor.
4095 if (descriptors->GetValue(descriptor) != *new_wrapped_type) { 4111 if (descriptors->GetValue(descriptor) != *new_wrapped_type) {
4112 DCHECK_IMPLIES(!FLAG_track_constant_fields, new_constness == kMutable);
4096 Descriptor d = Descriptor::DataField( 4113 Descriptor d = Descriptor::DataField(
4097 name, descriptors->GetFieldIndex(descriptor), details.attributes(), 4114 name, descriptors->GetFieldIndex(descriptor), details.attributes(),
4098 kMutable, new_representation, new_wrapped_type); 4115 new_constness, new_representation, new_wrapped_type);
4099 descriptors->Replace(descriptor, &d); 4116 descriptors->Replace(descriptor, &d);
4100 } 4117 }
4101 } 4118 }
4102 } 4119 }
4103 4120
4104 bool FieldTypeIsCleared(Representation rep, FieldType* type) { 4121 bool FieldTypeIsCleared(Representation rep, FieldType* type) {
4105 return type->IsNone() && rep.IsHeapObject(); 4122 return type->IsNone() && rep.IsHeapObject();
4106 } 4123 }
4107 4124
4108 4125
(...skipping 10 matching lines...) Expand all
4119 return FieldType::Any(isolate); 4136 return FieldType::Any(isolate);
4120 } 4137 }
4121 if (type1->NowIs(type2)) return type2; 4138 if (type1->NowIs(type2)) return type2;
4122 if (type2->NowIs(type1)) return type1; 4139 if (type2->NowIs(type1)) return type1;
4123 return FieldType::Any(isolate); 4140 return FieldType::Any(isolate);
4124 } 4141 }
4125 4142
4126 4143
4127 // static 4144 // static
4128 void Map::GeneralizeField(Handle<Map> map, int modify_index, 4145 void Map::GeneralizeField(Handle<Map> map, int modify_index,
4146 PropertyConstness new_constness,
4129 Representation new_representation, 4147 Representation new_representation,
4130 Handle<FieldType> new_field_type) { 4148 Handle<FieldType> new_field_type) {
4131 Isolate* isolate = map->GetIsolate(); 4149 Isolate* isolate = map->GetIsolate();
4132 4150
4133 // Check if we actually need to generalize the field type at all. 4151 // Check if we actually need to generalize the field type at all.
4134 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate); 4152 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
4135 Representation old_representation = 4153 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
4136 old_descriptors->GetDetails(modify_index).representation(); 4154 PropertyConstness old_constness = old_details.constness();
4155 Representation old_representation = old_details.representation();
4137 Handle<FieldType> old_field_type(old_descriptors->GetFieldType(modify_index), 4156 Handle<FieldType> old_field_type(old_descriptors->GetFieldType(modify_index),
4138 isolate); 4157 isolate);
4139 4158
4140 if (old_representation.Equals(new_representation) && 4159 if (old_constness == new_constness &&
4160 old_representation.Equals(new_representation) &&
4141 !FieldTypeIsCleared(new_representation, *new_field_type) && 4161 !FieldTypeIsCleared(new_representation, *new_field_type) &&
4142 // Checking old_field_type for being cleared is not necessary because 4162 // Checking old_field_type for being cleared is not necessary because
4143 // the NowIs check below would fail anyway in that case. 4163 // the NowIs check below would fail anyway in that case.
4144 new_field_type->NowIs(old_field_type)) { 4164 new_field_type->NowIs(old_field_type)) {
4145 DCHECK(GeneralizeFieldType(old_representation, old_field_type, 4165 DCHECK(GeneralizeFieldType(old_representation, old_field_type,
4146 new_representation, new_field_type, isolate) 4166 new_representation, new_field_type, isolate)
4147 ->NowIs(old_field_type)); 4167 ->NowIs(old_field_type));
4148 return; 4168 return;
4149 } 4169 }
4150 4170
4151 // Determine the field owner. 4171 // Determine the field owner.
4152 Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate); 4172 Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
4153 Handle<DescriptorArray> descriptors( 4173 Handle<DescriptorArray> descriptors(
4154 field_owner->instance_descriptors(), isolate); 4174 field_owner->instance_descriptors(), isolate);
4155 DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index)); 4175 DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
4156 4176
4157 new_field_type = 4177 new_field_type =
4158 Map::GeneralizeFieldType(old_representation, old_field_type, 4178 Map::GeneralizeFieldType(old_representation, old_field_type,
4159 new_representation, new_field_type, isolate); 4179 new_representation, new_field_type, isolate);
4160 4180
4161 PropertyDetails details = descriptors->GetDetails(modify_index); 4181 PropertyDetails details = descriptors->GetDetails(modify_index);
4162 Handle<Name> name(descriptors->GetKey(modify_index)); 4182 Handle<Name> name(descriptors->GetKey(modify_index));
4163 4183
4164 Handle<Object> wrapped_type(WrapFieldType(new_field_type)); 4184 Handle<Object> wrapped_type(WrapFieldType(new_field_type));
4165 field_owner->UpdateFieldType(modify_index, name, new_representation, 4185 field_owner->UpdateFieldType(modify_index, name, new_constness,
4166 wrapped_type); 4186 new_representation, wrapped_type);
4167 field_owner->dependent_code()->DeoptimizeDependentCodeGroup( 4187 field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
4168 isolate, DependentCode::kFieldOwnerGroup); 4188 isolate, DependentCode::kFieldOwnerGroup);
4169 4189
4170 if (FLAG_trace_generalization) { 4190 if (FLAG_trace_generalization) {
4171 map->PrintGeneralization( 4191 map->PrintGeneralization(
4172 stdout, "field type generalization", modify_index, 4192 stdout, "field type generalization", modify_index,
4173 map->NumberOfOwnDescriptors(), map->NumberOfOwnDescriptors(), false, 4193 map->NumberOfOwnDescriptors(), map->NumberOfOwnDescriptors(), false,
4174 details.representation(), details.representation(), old_field_type, 4194 details.representation(), details.representation(), old_field_type,
4175 MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>()); 4195 MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>());
4176 } 4196 }
4177 } 4197 }
4178 4198
4179 // TODO(ishell): remove. 4199 // TODO(ishell): remove.
4180 // static 4200 // static
4181 Handle<Map> Map::ReconfigureProperty(Handle<Map> map, int modify_index, 4201 Handle<Map> Map::ReconfigureProperty(Handle<Map> map, int modify_index,
4182 PropertyKind new_kind, 4202 PropertyKind new_kind,
4183 PropertyAttributes new_attributes, 4203 PropertyAttributes new_attributes,
4184 Representation new_representation, 4204 Representation new_representation,
4185 Handle<FieldType> new_field_type) { 4205 Handle<FieldType> new_field_type) {
4186 DCHECK_EQ(kData, new_kind); // Only kData case is supported. 4206 DCHECK_EQ(kData, new_kind); // Only kData case is supported.
4187 MapUpdater mu(map->GetIsolate(), map); 4207 MapUpdater mu(map->GetIsolate(), map);
4188 return mu.ReconfigureToDataField(modify_index, new_attributes, 4208 return mu.ReconfigureToDataField(modify_index, new_attributes, kConst,
4189 new_representation, new_field_type); 4209 new_representation, new_field_type);
4190 } 4210 }
4191 4211
4192 // TODO(ishell): remove. 4212 // TODO(ishell): remove.
4193 // static 4213 // static
4194 Handle<Map> Map::ReconfigureElementsKind(Handle<Map> map, 4214 Handle<Map> Map::ReconfigureElementsKind(Handle<Map> map,
4195 ElementsKind new_elements_kind) { 4215 ElementsKind new_elements_kind) {
4196 MapUpdater mu(map->GetIsolate(), map); 4216 MapUpdater mu(map->GetIsolate(), map);
4197 return mu.ReconfigureElementsKind(new_elements_kind); 4217 return mu.ReconfigureElementsKind(new_elements_kind);
4198 } 4218 }
4199 4219
4200 // Generalize all fields and update the transition tree. 4220 // Generalize all fields and update the transition tree.
4201 Handle<Map> Map::GeneralizeAllFields(Handle<Map> map) { 4221 Handle<Map> Map::GeneralizeAllFields(Handle<Map> map) {
4202 Isolate* isolate = map->GetIsolate(); 4222 Isolate* isolate = map->GetIsolate();
4203 Handle<FieldType> any_type = FieldType::Any(isolate); 4223 Handle<FieldType> any_type = FieldType::Any(isolate);
4204 4224
4205 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 4225 Handle<DescriptorArray> descriptors(map->instance_descriptors());
4206 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) { 4226 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
4207 PropertyDetails details = descriptors->GetDetails(i); 4227 PropertyDetails details = descriptors->GetDetails(i);
4208 if (details.location() == kField) { 4228 if (details.location() == kField) {
4209 DCHECK_EQ(kData, details.kind()); 4229 DCHECK_EQ(kData, details.kind());
4210 MapUpdater mu(isolate, map); 4230 MapUpdater mu(isolate, map);
4211 map = mu.ReconfigureToDataField(i, details.attributes(), 4231 map = mu.ReconfigureToDataField(i, details.attributes(), kMutable,
4212 Representation::Tagged(), any_type); 4232 Representation::Tagged(), any_type);
4213 } 4233 }
4214 } 4234 }
4215 return map; 4235 return map;
4216 } 4236 }
4217 4237
4218 4238
4219 // static 4239 // static
4220 MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) { 4240 MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) {
4221 DisallowHeapAllocation no_allocation; 4241 DisallowHeapAllocation no_allocation;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
4279 } 4299 }
4280 DCHECK_EQ(kData, old_details.kind()); 4300 DCHECK_EQ(kData, old_details.kind());
4281 if (old_details.location() == kField) { 4301 if (old_details.location() == kField) {
4282 FieldType* old_type = old_descriptors->GetFieldType(i); 4302 FieldType* old_type = old_descriptors->GetFieldType(i);
4283 if (FieldTypeIsCleared(old_details.representation(), old_type) || 4303 if (FieldTypeIsCleared(old_details.representation(), old_type) ||
4284 !old_type->NowIs(new_type)) { 4304 !old_type->NowIs(new_type)) {
4285 return nullptr; 4305 return nullptr;
4286 } 4306 }
4287 } else { 4307 } else {
4288 DCHECK_EQ(kDescriptor, old_details.location()); 4308 DCHECK_EQ(kDescriptor, old_details.location());
4309 DCHECK(!FLAG_track_constant_fields);
4289 Object* old_value = old_descriptors->GetValue(i); 4310 Object* old_value = old_descriptors->GetValue(i);
4290 if (!new_type->NowContains(old_value)) { 4311 if (!new_type->NowContains(old_value)) {
4291 return nullptr; 4312 return nullptr;
4292 } 4313 }
4293 } 4314 }
4294 4315
4295 } else { 4316 } else {
4296 DCHECK_EQ(kAccessor, new_details.kind()); 4317 DCHECK_EQ(kAccessor, new_details.kind());
4297 #ifdef DEBUG 4318 #ifdef DEBUG
4298 FieldType* new_type = new_descriptors->GetFieldType(i); 4319 FieldType* new_type = new_descriptors->GetFieldType(i);
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
4601 // TODO(neis): According to the spec, this should throw a TypeError. 4622 // TODO(neis): According to the spec, this should throw a TypeError.
4602 } 4623 }
4603 } 4624 }
4604 } 4625 }
4605 4626
4606 // Possibly migrate to the most up-to-date map that will be able to store 4627 // Possibly migrate to the most up-to-date map that will be able to store
4607 // |value| under it->name(). 4628 // |value| under it->name().
4608 it->PrepareForDataProperty(to_assign); 4629 it->PrepareForDataProperty(to_assign);
4609 4630
4610 // Write the property value. 4631 // Write the property value.
4611 it->WriteDataValue(to_assign); 4632 it->WriteDataValue(to_assign, false);
4612 4633
4613 #if VERIFY_HEAP 4634 #if VERIFY_HEAP
4614 if (FLAG_verify_heap) { 4635 if (FLAG_verify_heap) {
4615 receiver->JSObjectVerify(); 4636 receiver->JSObjectVerify();
4616 } 4637 }
4617 #endif 4638 #endif
4618 return Just(true); 4639 return Just(true);
4619 } 4640 }
4620 4641
4621 4642
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
4675 } else { 4696 } else {
4676 it->UpdateProtector(); 4697 it->UpdateProtector();
4677 // Migrate to the most up-to-date map that will be able to store |value| 4698 // Migrate to the most up-to-date map that will be able to store |value|
4678 // under it->name() with |attributes|. 4699 // under it->name() with |attributes|.
4679 it->PrepareTransitionToDataProperty(receiver, value, attributes, 4700 it->PrepareTransitionToDataProperty(receiver, value, attributes,
4680 store_mode); 4701 store_mode);
4681 DCHECK_EQ(LookupIterator::TRANSITION, it->state()); 4702 DCHECK_EQ(LookupIterator::TRANSITION, it->state());
4682 it->ApplyTransitionToDataProperty(receiver); 4703 it->ApplyTransitionToDataProperty(receiver);
4683 4704
4684 // Write the property value. 4705 // Write the property value.
4685 it->WriteDataValue(value); 4706 it->WriteDataValue(value, true);
4686 4707
4687 #if VERIFY_HEAP 4708 #if VERIFY_HEAP
4688 if (FLAG_verify_heap) { 4709 if (FLAG_verify_heap) {
4689 receiver->JSObjectVerify(); 4710 receiver->JSObjectVerify();
4690 } 4711 }
4691 #endif 4712 #endif
4692 } 4713 }
4693 4714
4694 return Just(true); 4715 return Just(true);
4695 } 4716 }
(...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after
5709 int instance_descriptor_length = iteration_order->length(); 5730 int instance_descriptor_length = iteration_order->length();
5710 int number_of_fields = 0; 5731 int number_of_fields = 0;
5711 5732
5712 // Compute the length of the instance descriptor. 5733 // Compute the length of the instance descriptor.
5713 for (int i = 0; i < instance_descriptor_length; i++) { 5734 for (int i = 0; i < instance_descriptor_length; i++) {
5714 int index = Smi::cast(iteration_order->get(i))->value(); 5735 int index = Smi::cast(iteration_order->get(i))->value();
5715 DCHECK(dictionary->IsKey(isolate, dictionary->KeyAt(index))); 5736 DCHECK(dictionary->IsKey(isolate, dictionary->KeyAt(index)));
5716 5737
5717 PropertyKind kind = dictionary->DetailsAt(index).kind(); 5738 PropertyKind kind = dictionary->DetailsAt(index).kind();
5718 if (kind == kData) { 5739 if (kind == kData) {
5719 Object* value = dictionary->ValueAt(index); 5740 if (FLAG_track_constant_fields) {
5720 if (!value->IsJSFunction()) {
5721 number_of_fields += 1; 5741 number_of_fields += 1;
5742 } else {
5743 Object* value = dictionary->ValueAt(index);
5744 if (!value->IsJSFunction()) {
5745 number_of_fields += 1;
5746 }
5722 } 5747 }
5723 } 5748 }
5724 } 5749 }
5725 5750
5726 Handle<Map> old_map(object->map(), isolate); 5751 Handle<Map> old_map(object->map(), isolate);
5727 5752
5728 int inobject_props = old_map->GetInObjectProperties(); 5753 int inobject_props = old_map->GetInObjectProperties();
5729 5754
5730 // Allocate new map. 5755 // Allocate new map.
5731 Handle<Map> new_map = Map::CopyDropDescriptors(old_map); 5756 Handle<Map> new_map = Map::CopyDropDescriptors(old_map);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
5782 5807
5783 Object* value = dictionary->ValueAt(index); 5808 Object* value = dictionary->ValueAt(index);
5784 5809
5785 PropertyDetails details = dictionary->DetailsAt(index); 5810 PropertyDetails details = dictionary->DetailsAt(index);
5786 DCHECK_EQ(kField, details.location()); 5811 DCHECK_EQ(kField, details.location());
5787 DCHECK_EQ(kMutable, details.constness()); 5812 DCHECK_EQ(kMutable, details.constness());
5788 int enumeration_index = details.dictionary_index(); 5813 int enumeration_index = details.dictionary_index();
5789 5814
5790 Descriptor d; 5815 Descriptor d;
5791 if (details.kind() == kData) { 5816 if (details.kind() == kData) {
5792 if (value->IsJSFunction()) { 5817 if (!FLAG_track_constant_fields && value->IsJSFunction()) {
5793 d = Descriptor::DataConstant(key, handle(value, isolate), 5818 d = Descriptor::DataConstant(key, handle(value, isolate),
5794 details.attributes()); 5819 details.attributes());
5795 } else { 5820 } else {
5796 d = Descriptor::DataField( 5821 d = Descriptor::DataField(
5797 key, current_offset, details.attributes(), 5822 key, current_offset, details.attributes(), kDefaultFieldConstness,
5798 // TODO(verwaest): value->OptimalRepresentation(); 5823 // TODO(verwaest): value->OptimalRepresentation();
5799 Representation::Tagged()); 5824 Representation::Tagged(), FieldType::Any(isolate));
5800 } 5825 }
5801 } else { 5826 } else {
5802 DCHECK_EQ(kAccessor, details.kind()); 5827 DCHECK_EQ(kAccessor, details.kind());
5803 d = Descriptor::AccessorConstant(key, handle(value, isolate), 5828 d = Descriptor::AccessorConstant(key, handle(value, isolate),
5804 details.attributes()); 5829 details.attributes());
5805 } 5830 }
5806 details = d.GetDetails(); 5831 details = d.GetDetails();
5807 if (details.location() == kField) { 5832 if (details.location() == kField) {
5808 if (current_offset < inobject_props) { 5833 if (current_offset < inobject_props) {
5809 object->InObjectPropertyAtPut(current_offset, value, 5834 object->InObjectPropertyAtPut(current_offset, value,
(...skipping 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after
7000 Handle<Object> value = 7025 Handle<Object> value =
7001 desc->has_value() 7026 desc->has_value()
7002 ? desc->value() 7027 ? desc->value()
7003 : Handle<Object>::cast(isolate->factory()->undefined_value()); 7028 : Handle<Object>::cast(isolate->factory()->undefined_value());
7004 7029
7005 LookupIterator it(proxy, private_name, proxy); 7030 LookupIterator it(proxy, private_name, proxy);
7006 7031
7007 if (it.IsFound()) { 7032 if (it.IsFound()) {
7008 DCHECK_EQ(LookupIterator::DATA, it.state()); 7033 DCHECK_EQ(LookupIterator::DATA, it.state());
7009 DCHECK_EQ(DONT_ENUM, it.property_attributes()); 7034 DCHECK_EQ(DONT_ENUM, it.property_attributes());
7010 it.WriteDataValue(value); 7035 it.WriteDataValue(value, false);
7011 return Just(true); 7036 return Just(true);
7012 } 7037 }
7013 7038
7014 Handle<NameDictionary> dict(proxy->property_dictionary()); 7039 Handle<NameDictionary> dict(proxy->property_dictionary());
7015 PropertyDetails details(kData, DONT_ENUM, 0, PropertyCellType::kNoCell); 7040 PropertyDetails details(kData, DONT_ENUM, 0, PropertyCellType::kNoCell);
7016 Handle<NameDictionary> result = 7041 Handle<NameDictionary> result =
7017 NameDictionary::Add(dict, private_name, value, details); 7042 NameDictionary::Add(dict, private_name, value, details);
7018 if (!dict.is_identical_to(result)) proxy->set_properties(*result); 7043 if (!dict.is_identical_to(result)) proxy->set_properties(*result);
7019 return Just(true); 7044 return Just(true);
7020 } 7045 }
(...skipping 2132 matching lines...) Expand 10 before | Expand all | Expand 10 after
9153 ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind()) 9178 ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind())
9154 ? SLOW_STRING_WRAPPER_ELEMENTS 9179 ? SLOW_STRING_WRAPPER_ELEMENTS
9155 : DICTIONARY_ELEMENTS; 9180 : DICTIONARY_ELEMENTS;
9156 new_map->set_elements_kind(new_kind); 9181 new_map->set_elements_kind(new_kind);
9157 } 9182 }
9158 return new_map; 9183 return new_map;
9159 } 9184 }
9160 9185
9161 namespace { 9186 namespace {
9162 9187
9163 bool CanHoldValue(DescriptorArray* descriptors, int descriptor, Object* value) { 9188 bool CanHoldValue(DescriptorArray* descriptors, int descriptor,
9189 PropertyConstness constness, Object* value) {
9164 PropertyDetails details = descriptors->GetDetails(descriptor); 9190 PropertyDetails details = descriptors->GetDetails(descriptor);
9165 if (details.location() == kField) { 9191 if (details.location() == kField) {
9166 DCHECK_EQ(kMutable, details.constness());
9167 if (details.kind() == kData) { 9192 if (details.kind() == kData) {
9168 return value->FitsRepresentation(details.representation()) && 9193 return IsGeneralizableTo(constness, details.constness()) &&
9194 value->FitsRepresentation(details.representation()) &&
9169 descriptors->GetFieldType(descriptor)->NowContains(value); 9195 descriptors->GetFieldType(descriptor)->NowContains(value);
9170 } else { 9196 } else {
9171 DCHECK_EQ(kAccessor, details.kind()); 9197 DCHECK_EQ(kAccessor, details.kind());
9172 UNREACHABLE();
9173 return false; 9198 return false;
9174 } 9199 }
9175 9200
9176 } else { 9201 } else {
9177 DCHECK_EQ(kDescriptor, details.location()); 9202 DCHECK_EQ(kDescriptor, details.location());
9178 DCHECK_EQ(kConst, details.constness()); 9203 DCHECK_EQ(kConst, details.constness());
9179 if (details.kind() == kData) { 9204 if (details.kind() == kData) {
9205 DCHECK(!FLAG_track_constant_fields);
9180 DCHECK(descriptors->GetValue(descriptor) != value || 9206 DCHECK(descriptors->GetValue(descriptor) != value ||
9181 value->FitsRepresentation(details.representation())); 9207 value->FitsRepresentation(details.representation()));
9182 return descriptors->GetValue(descriptor) == value; 9208 return descriptors->GetValue(descriptor) == value;
9183 } else { 9209 } else {
9184 DCHECK_EQ(kAccessor, details.kind()); 9210 DCHECK_EQ(kAccessor, details.kind());
9185 return false; 9211 return false;
9186 } 9212 }
9187 } 9213 }
9188 UNREACHABLE(); 9214 UNREACHABLE();
9189 return false; 9215 return false;
9190 } 9216 }
9191 9217
9192 Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor, 9218 Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor,
9219 PropertyConstness constness,
9193 Handle<Object> value) { 9220 Handle<Object> value) {
9194 if (CanHoldValue(map->instance_descriptors(), descriptor, *value)) return map; 9221 if (CanHoldValue(map->instance_descriptors(), descriptor, constness,
9222 *value)) {
9223 return map;
9224 }
9195 9225
9196 Isolate* isolate = map->GetIsolate(); 9226 Isolate* isolate = map->GetIsolate();
9197 PropertyAttributes attributes = 9227 PropertyAttributes attributes =
9198 map->instance_descriptors()->GetDetails(descriptor).attributes(); 9228 map->instance_descriptors()->GetDetails(descriptor).attributes();
9199 Representation representation = value->OptimalRepresentation(); 9229 Representation representation = value->OptimalRepresentation();
9200 Handle<FieldType> type = value->OptimalType(isolate, representation); 9230 Handle<FieldType> type = value->OptimalType(isolate, representation);
9201 9231
9202 MapUpdater mu(isolate, map); 9232 MapUpdater mu(isolate, map);
9203 Handle<Map> new_map = 9233 Handle<Map> new_map = mu.ReconfigureToDataField(
9204 mu.ReconfigureToDataField(descriptor, attributes, representation, type); 9234 descriptor, attributes, constness, representation, type);
9205 new_map->set_migration_target(true); 9235 new_map->set_migration_target(true);
9206 return new_map; 9236 return new_map;
9207 } 9237 }
9208 9238
9209 } // namespace 9239 } // namespace
9210 9240
9211 // static 9241 // static
9212 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor, 9242 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
9243 PropertyConstness constness,
9213 Handle<Object> value) { 9244 Handle<Object> value) {
9214 // Dictionaries can store any property value. 9245 // Dictionaries can store any property value.
9215 DCHECK(!map->is_dictionary_map()); 9246 DCHECK(!map->is_dictionary_map());
9216 // Update to the newest map before storing the property. 9247 // Update to the newest map before storing the property.
9217 return UpdateDescriptorForValue(Update(map), descriptor, value); 9248 return UpdateDescriptorForValue(Update(map), descriptor, constness, value);
9218 } 9249 }
9219 9250
9220
9221 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, 9251 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
9222 Handle<Object> value, 9252 Handle<Object> value,
9223 PropertyAttributes attributes, 9253 PropertyAttributes attributes,
9254 PropertyConstness constness,
9224 StoreFromKeyed store_mode) { 9255 StoreFromKeyed store_mode) {
9225 RuntimeCallTimerScope stats_scope( 9256 RuntimeCallTimerScope stats_scope(
9226 *map, map->is_prototype_map() 9257 *map, map->is_prototype_map()
9227 ? &RuntimeCallStats::PrototypeMap_TransitionToDataProperty 9258 ? &RuntimeCallStats::PrototypeMap_TransitionToDataProperty
9228 : &RuntimeCallStats::Map_TransitionToDataProperty); 9259 : &RuntimeCallStats::Map_TransitionToDataProperty);
9229 9260
9230 DCHECK(name->IsUniqueName()); 9261 DCHECK(name->IsUniqueName());
9231 DCHECK(!map->is_dictionary_map()); 9262 DCHECK(!map->is_dictionary_map());
9232 9263
9233 // Migrate to the newest map before storing the property. 9264 // Migrate to the newest map before storing the property.
9234 map = Update(map); 9265 map = Update(map);
9235 9266
9236 Map* maybe_transition = 9267 Map* maybe_transition =
9237 TransitionArray::SearchTransition(*map, kData, *name, attributes); 9268 TransitionArray::SearchTransition(*map, kData, *name, attributes);
9238 if (maybe_transition != NULL) { 9269 if (maybe_transition != NULL) {
9239 Handle<Map> transition(maybe_transition); 9270 Handle<Map> transition(maybe_transition);
9240 int descriptor = transition->LastAdded(); 9271 int descriptor = transition->LastAdded();
9241 9272
9242 DCHECK_EQ(attributes, transition->instance_descriptors() 9273 DCHECK_EQ(attributes, transition->instance_descriptors()
9243 ->GetDetails(descriptor) 9274 ->GetDetails(descriptor)
9244 .attributes()); 9275 .attributes());
9245 9276
9246 return UpdateDescriptorForValue(transition, descriptor, value); 9277 return UpdateDescriptorForValue(transition, descriptor, constness, value);
9247 } 9278 }
9248 9279
9249 TransitionFlag flag = INSERT_TRANSITION; 9280 TransitionFlag flag = INSERT_TRANSITION;
9250 MaybeHandle<Map> maybe_map; 9281 MaybeHandle<Map> maybe_map;
9251 if (value->IsJSFunction()) { 9282 if (!FLAG_track_constant_fields && value->IsJSFunction()) {
9252 maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag); 9283 maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
9253 } else if (!map->TooManyFastProperties(store_mode)) { 9284 } else if (!map->TooManyFastProperties(store_mode)) {
9254 Isolate* isolate = name->GetIsolate(); 9285 Isolate* isolate = name->GetIsolate();
9255 Representation representation = value->OptimalRepresentation(); 9286 Representation representation = value->OptimalRepresentation();
9256 Handle<FieldType> type = value->OptimalType(isolate, representation); 9287 Handle<FieldType> type = value->OptimalType(isolate, representation);
9257 maybe_map = 9288 maybe_map = Map::CopyWithField(map, name, type, attributes, constness,
9258 Map::CopyWithField(map, name, type, attributes, representation, flag); 9289 representation, flag);
9259 } 9290 }
9260 9291
9261 Handle<Map> result; 9292 Handle<Map> result;
9262 if (!maybe_map.ToHandle(&result)) { 9293 if (!maybe_map.ToHandle(&result)) {
9263 #if TRACE_MAPS 9294 #if TRACE_MAPS
9264 if (FLAG_trace_maps) { 9295 if (FLAG_trace_maps) {
9265 Vector<char> name_buffer = Vector<char>::New(100); 9296 Vector<char> name_buffer = Vector<char>::New(100);
9266 name->NameShortPrint(name_buffer); 9297 name->NameShortPrint(name_buffer);
9267 Vector<char> buffer = Vector<char>::New(128); 9298 Vector<char> buffer = Vector<char>::New(128);
9268 SNPrintF(buffer, "TooManyFastProperties %s", name_buffer.start()); 9299 SNPrintF(buffer, "TooManyFastProperties %s", name_buffer.start());
(...skipping 24 matching lines...) Expand all
9293 9324
9294 if (FLAG_trace_generalization) { 9325 if (FLAG_trace_generalization) {
9295 map->PrintReconfiguration(stdout, descriptor, kind, attributes); 9326 map->PrintReconfiguration(stdout, descriptor, kind, attributes);
9296 } 9327 }
9297 9328
9298 Isolate* isolate = map->GetIsolate(); 9329 Isolate* isolate = map->GetIsolate();
9299 9330
9300 MapUpdater mu(isolate, map); 9331 MapUpdater mu(isolate, map);
9301 DCHECK_EQ(kData, kind); // Only kData case is supported so far. 9332 DCHECK_EQ(kData, kind); // Only kData case is supported so far.
9302 Handle<Map> new_map = mu.ReconfigureToDataField( 9333 Handle<Map> new_map = mu.ReconfigureToDataField(
9303 descriptor, attributes, Representation::None(), FieldType::None(isolate)); 9334 descriptor, attributes, kDefaultFieldConstness, Representation::None(),
9335 FieldType::None(isolate));
9304 return new_map; 9336 return new_map;
9305 } 9337 }
9306 9338
9307 Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map, 9339 Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map,
9308 Handle<Name> name, int descriptor, 9340 Handle<Name> name, int descriptor,
9309 Handle<Object> getter, 9341 Handle<Object> getter,
9310 Handle<Object> setter, 9342 Handle<Object> setter,
9311 PropertyAttributes attributes) { 9343 PropertyAttributes attributes) {
9312 RuntimeCallTimerScope stats_scope( 9344 RuntimeCallTimerScope stats_scope(
9313 isolate, 9345 isolate,
(...skipping 10877 matching lines...) Expand 10 before | Expand all | Expand 10 after
20191 // depend on this. 20223 // depend on this.
20192 return DICTIONARY_ELEMENTS; 20224 return DICTIONARY_ELEMENTS;
20193 } 20225 }
20194 DCHECK_LE(kind, LAST_ELEMENTS_KIND); 20226 DCHECK_LE(kind, LAST_ELEMENTS_KIND);
20195 return kind; 20227 return kind;
20196 } 20228 }
20197 } 20229 }
20198 20230
20199 } // namespace internal 20231 } // namespace internal
20200 } // namespace v8 20232 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698