Handlify Map::CopyDropDescriptors().

* And contain knowledge better in TransitionArray and DescriptorArray (for example WhitenessWitness is now private to DescriptorArray).
* And remove some factory methods
* And handlify some other things.

R=verwaest@chromium.org

Review URL: https://codereview.chromium.org/234783002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20686 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mvstanton@chromium.org 2014-04-11 12:13:53 +00:00
parent 93c9717473
commit c5eaf80707
9 changed files with 292 additions and 405 deletions

View File

@ -383,8 +383,7 @@ static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
void Genesis::SetFunctionInstanceDescriptor(
Handle<Map> map, PrototypePropertyMode prototypeMode) {
int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5;
Handle<DescriptorArray> descriptors(factory()->NewDescriptorArray(0, size));
DescriptorArray::WhitenessWitness witness(*descriptors);
Map::EnsureDescriptorSlack(map, size);
Handle<Foreign> length(factory()->NewForeign(&Accessors::FunctionLength));
Handle<Foreign> name(factory()->NewForeign(&Accessors::FunctionName));
@ -396,23 +395,22 @@ void Genesis::SetFunctionInstanceDescriptor(
}
PropertyAttributes attribs = static_cast<PropertyAttributes>(
DONT_ENUM | DONT_DELETE | READ_ONLY);
map->set_instance_descriptors(*descriptors);
{ // Add length.
CallbacksDescriptor d(factory()->length_string(), length, attribs);
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
}
{ // Add name.
CallbacksDescriptor d(factory()->name_string(), name, attribs);
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
}
{ // Add arguments.
CallbacksDescriptor d(factory()->arguments_string(), args, attribs);
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
}
{ // Add caller.
CallbacksDescriptor d(factory()->caller_string(), caller, attribs);
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
}
if (prototypeMode != DONT_ADD_PROTOTYPE) {
// Add prototype.
@ -420,7 +418,7 @@ void Genesis::SetFunctionInstanceDescriptor(
attribs = static_cast<PropertyAttributes>(attribs & ~READ_ONLY);
}
CallbacksDescriptor d(factory()->prototype_string(), prototype, attribs);
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
}
}
@ -522,8 +520,7 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
void Genesis::SetStrictFunctionInstanceDescriptor(
Handle<Map> map, PrototypePropertyMode prototypeMode) {
int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5;
Handle<DescriptorArray> descriptors(factory()->NewDescriptorArray(0, size));
DescriptorArray::WhitenessWitness witness(*descriptors);
Map::EnsureDescriptorSlack(map, size);
Handle<Foreign> length(factory()->NewForeign(&Accessors::FunctionLength));
Handle<Foreign> name(factory()->NewForeign(&Accessors::FunctionName));
@ -537,31 +534,30 @@ void Genesis::SetStrictFunctionInstanceDescriptor(
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
PropertyAttributes ro_attribs =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
map->set_instance_descriptors(*descriptors);
{ // Add length.
CallbacksDescriptor d(factory()->length_string(), length, ro_attribs);
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
}
{ // Add name.
CallbacksDescriptor d(factory()->name_string(), name, ro_attribs);
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
}
{ // Add arguments.
CallbacksDescriptor d(factory()->arguments_string(), arguments,
rw_attribs);
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
}
{ // Add caller.
CallbacksDescriptor d(factory()->caller_string(), caller, rw_attribs);
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
}
if (prototypeMode != DONT_ADD_PROTOTYPE) {
// Add prototype.
PropertyAttributes attribs =
prototypeMode == ADD_WRITEABLE_PROTOTYPE ? rw_attribs : ro_attribs;
CallbacksDescriptor d(factory()->prototype_string(), prototype, attribs);
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
}
}
@ -861,19 +857,15 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
// This assert protects an optimization in
// HGraphBuilder::JSArrayBuilder::EmitMapCode()
ASSERT(initial_map->elements_kind() == GetInitialFastElementsKind());
Handle<DescriptorArray> array_descriptors(
factory->NewDescriptorArray(0, 1));
DescriptorArray::WhitenessWitness witness(*array_descriptors);
Map::EnsureDescriptorSlack(initial_map, 1);
Handle<Foreign> array_length(factory->NewForeign(&Accessors::ArrayLength));
PropertyAttributes attribs = static_cast<PropertyAttributes>(
DONT_ENUM | DONT_DELETE);
initial_map->set_instance_descriptors(*array_descriptors);
{ // Add length.
CallbacksDescriptor d(factory->length_string(), array_length, attribs);
array_function->initial_map()->AppendDescriptor(&d, witness);
array_function->initial_map()->AppendDescriptor(&d);
}
// array_function is used internally. JS code creating array object should
@ -916,19 +908,16 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
Handle<Map> string_map =
Handle<Map>(native_context()->string_function()->initial_map());
Handle<DescriptorArray> string_descriptors(
factory->NewDescriptorArray(0, 1));
DescriptorArray::WhitenessWitness witness(*string_descriptors);
Map::EnsureDescriptorSlack(string_map, 1);
Handle<Foreign> string_length(
factory->NewForeign(&Accessors::StringLength));
PropertyAttributes attribs = static_cast<PropertyAttributes>(
DONT_ENUM | DONT_DELETE | READ_ONLY);
string_map->set_instance_descriptors(*string_descriptors);
{ // Add length.
CallbacksDescriptor d(factory->length_string(), string_length, attribs);
string_map->AppendDescriptor(&d, witness);
string_map->AppendDescriptor(&d);
}
}
@ -958,9 +947,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
PropertyAttributes final =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(0, 5);
DescriptorArray::WhitenessWitness witness(*descriptors);
initial_map->set_instance_descriptors(*descriptors);
Map::EnsureDescriptorSlack(initial_map, 5);
{
// ECMA-262, section 15.10.7.1.
@ -968,7 +955,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kSourceFieldIndex,
final,
Representation::Tagged());
initial_map->AppendDescriptor(&field, witness);
initial_map->AppendDescriptor(&field);
}
{
// ECMA-262, section 15.10.7.2.
@ -976,7 +963,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kGlobalFieldIndex,
final,
Representation::Tagged());
initial_map->AppendDescriptor(&field, witness);
initial_map->AppendDescriptor(&field);
}
{
// ECMA-262, section 15.10.7.3.
@ -984,7 +971,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kIgnoreCaseFieldIndex,
final,
Representation::Tagged());
initial_map->AppendDescriptor(&field, witness);
initial_map->AppendDescriptor(&field);
}
{
// ECMA-262, section 15.10.7.4.
@ -992,7 +979,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kMultilineFieldIndex,
final,
Representation::Tagged());
initial_map->AppendDescriptor(&field, witness);
initial_map->AppendDescriptor(&field);
}
{
// ECMA-262, section 15.10.7.5.
@ -1002,7 +989,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kLastIndexFieldIndex,
writable,
Representation::Tagged());
initial_map->AppendDescriptor(&field, witness);
initial_map->AppendDescriptor(&field);
}
initial_map->set_inobject_properties(5);
@ -1175,26 +1162,24 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE,
Heap::kStrictArgumentsObjectSize);
// Create the descriptor array for the arguments object.
Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(0, 3);
DescriptorArray::WhitenessWitness witness(*descriptors);
map->set_instance_descriptors(*descriptors);
Map::EnsureDescriptorSlack(map, 3);
{ // length
FieldDescriptor d(
factory->length_string(), 0, DONT_ENUM, Representation::Tagged());
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
}
{ // callee
CallbacksDescriptor d(factory->callee_string(),
callee,
attributes);
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
}
{ // caller
CallbacksDescriptor d(factory->caller_string(),
caller,
attributes);
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
}
map->set_function_with_prototype(true);
@ -1380,11 +1365,8 @@ void Genesis::InitializeExperimentalGlobal() {
object_function, JSGeneratorObject::kResultPropertyCount);
ASSERT(generator_result_map->inobject_properties() ==
JSGeneratorObject::kResultPropertyCount);
Handle<DescriptorArray> descriptors = factory()->NewDescriptorArray(0,
JSGeneratorObject::kResultPropertyCount);
DescriptorArray::WhitenessWitness witness(*descriptors);
generator_result_map->set_instance_descriptors(*descriptors);
Map::EnsureDescriptorSlack(
generator_result_map, JSGeneratorObject::kResultPropertyCount);
Handle<String> value_string = factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("value"));
@ -1392,7 +1374,7 @@ void Genesis::InitializeExperimentalGlobal() {
JSGeneratorObject::kResultValuePropertyIndex,
NONE,
Representation::Tagged());
generator_result_map->AppendDescriptor(&value_descr, witness);
generator_result_map->AppendDescriptor(&value_descr);
Handle<String> done_string = factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("done"));
@ -1400,7 +1382,7 @@ void Genesis::InitializeExperimentalGlobal() {
JSGeneratorObject::kResultDonePropertyIndex,
NONE,
Representation::Tagged());
generator_result_map->AppendDescriptor(&done_descr, witness);
generator_result_map->AppendDescriptor(&done_descr);
generator_result_map->set_unused_property_fields(0);
ASSERT_EQ(JSGeneratorObject::kResultSize,
@ -1606,20 +1588,17 @@ Handle<JSFunction> Genesis::InstallInternalArray(
array_function->set_initial_map(*initial_map);
// Make "length" magic on instances.
Handle<DescriptorArray> array_descriptors(
factory()->NewDescriptorArray(0, 1));
DescriptorArray::WhitenessWitness witness(*array_descriptors);
Map::EnsureDescriptorSlack(initial_map, 1);
Handle<Foreign> array_length(factory()->NewForeign(
&Accessors::ArrayLength));
PropertyAttributes attribs = static_cast<PropertyAttributes>(
DONT_ENUM | DONT_DELETE);
initial_map->set_instance_descriptors(*array_descriptors);
{ // Add length.
CallbacksDescriptor d(
factory()->length_string(), array_length, attribs);
array_function->initial_map()->AppendDescriptor(&d, witness);
array_function->initial_map()->AppendDescriptor(&d);
}
return array_function;
@ -1700,10 +1679,7 @@ bool Genesis::InstallNatives() {
native_context()->set_script_function(*script_fun);
Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
Handle<DescriptorArray> script_descriptors(
factory()->NewDescriptorArray(0, 13));
DescriptorArray::WhitenessWitness witness(*script_descriptors);
Map::EnsureDescriptorSlack(script_map, 13);
Handle<Foreign> script_source(
factory()->NewForeign(&Accessors::ScriptSource));
@ -1755,61 +1731,60 @@ bool Genesis::InstallNatives() {
factory()->NewForeign(&Accessors::ScriptEvalFromFunctionName));
PropertyAttributes attribs =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
script_map->set_instance_descriptors(*script_descriptors);
{
CallbacksDescriptor d(
factory()->source_string(), script_source, attribs);
script_map->AppendDescriptor(&d, witness);
script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(factory()->name_string(), script_name, attribs);
script_map->AppendDescriptor(&d, witness);
script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(id_string, script_id, attribs);
script_map->AppendDescriptor(&d, witness);
script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(line_offset_string, script_line_offset, attribs);
script_map->AppendDescriptor(&d, witness);
script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(
column_offset_string, script_column_offset, attribs);
script_map->AppendDescriptor(&d, witness);
script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(type_string, script_type, attribs);
script_map->AppendDescriptor(&d, witness);
script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(
compilation_type_string, script_compilation_type, attribs);
script_map->AppendDescriptor(&d, witness);
script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(line_ends_string, script_line_ends, attribs);
script_map->AppendDescriptor(&d, witness);
script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(
context_data_string, script_context_data, attribs);
script_map->AppendDescriptor(&d, witness);
script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(
eval_from_script_string, script_eval_from_script, attribs);
script_map->AppendDescriptor(&d, witness);
script_map->AppendDescriptor(&d);
}
{
@ -1817,7 +1792,7 @@ bool Genesis::InstallNatives() {
eval_from_script_position_string,
script_eval_from_script_position,
attribs);
script_map->AppendDescriptor(&d, witness);
script_map->AppendDescriptor(&d);
}
{
@ -1825,7 +1800,7 @@ bool Genesis::InstallNatives() {
eval_from_function_name_string,
script_eval_from_function_name,
attribs);
script_map->AppendDescriptor(&d, witness);
script_map->AppendDescriptor(&d);
}
// Allocate the empty script.
@ -1945,10 +1920,7 @@ bool Genesis::InstallNatives() {
initial_map->set_prototype(*array_prototype);
// Update map with length accessor from Array and add "index" and "input".
Handle<DescriptorArray> reresult_descriptors =
factory()->NewDescriptorArray(0, 3);
DescriptorArray::WhitenessWitness witness(*reresult_descriptors);
initial_map->set_instance_descriptors(*reresult_descriptors);
Map::EnsureDescriptorSlack(initial_map, 3);
{
JSFunction* array_function = native_context()->array_function();
@ -1962,14 +1934,14 @@ bool Genesis::InstallNatives() {
handle(array_descriptors->GetValue(old),
isolate()),
array_descriptors->GetDetails(old).attributes());
initial_map->AppendDescriptor(&desc, witness);
initial_map->AppendDescriptor(&desc);
}
{
FieldDescriptor index_field(factory()->index_string(),
JSRegExpResult::kIndexIndex,
NONE,
Representation::Tagged());
initial_map->AppendDescriptor(&index_field, witness);
initial_map->AppendDescriptor(&index_field);
}
{
@ -1977,7 +1949,7 @@ bool Genesis::InstallNatives() {
JSRegExpResult::kInputIndex,
NONE,
Representation::Tagged());
initial_map->AppendDescriptor(&input_field, witness);
initial_map->AppendDescriptor(&input_field);
}
initial_map->set_inobject_properties(2);

View File

@ -133,33 +133,6 @@ Handle<WeakHashTable> Factory::NewWeakHashTable(int at_least_space_for) {
}
Handle<DescriptorArray> Factory::NewDescriptorArray(int number_of_descriptors,
int slack) {
ASSERT(0 <= number_of_descriptors);
CALL_HEAP_FUNCTION(isolate(),
DescriptorArray::Allocate(
isolate(), number_of_descriptors, slack),
DescriptorArray);
}
Handle<TransitionArray> Factory::NewTransitionArray(int number_of_transitions) {
ASSERT(0 <= number_of_transitions);
CALL_HEAP_FUNCTION(isolate(),
TransitionArray::Allocate(
isolate(), number_of_transitions),
TransitionArray);
}
Handle<TransitionArray> Factory::NewSimpleTransitionArray(Handle<Map> target) {
CALL_HEAP_FUNCTION(isolate(),
TransitionArray::AllocateSimple(
isolate(), *target),
TransitionArray);
}
Handle<DeoptimizationInputData> Factory::NewDeoptimizationInputData(
int deopt_entry_count,
PretenureFlag pretenure) {

View File

@ -55,10 +55,6 @@ class Factory V8_FINAL {
Handle<WeakHashTable> NewWeakHashTable(int at_least_space_for);
Handle<DescriptorArray> NewDescriptorArray(int number_of_descriptors,
int slack = 0);
Handle<TransitionArray> NewTransitionArray(int number_of_transitions);
Handle<TransitionArray> NewSimpleTransitionArray(Handle<Map> target);
Handle<DeoptimizationInputData> NewDeoptimizationInputData(
int deopt_entry_count,
PretenureFlag pretenure);

View File

@ -2835,7 +2835,7 @@ void DescriptorArray::SwapSortedKeys(int first, int second) {
}
DescriptorArray::WhitenessWitness::WhitenessWitness(FixedArray* array)
DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
: marking_(array->GetHeap()->incremental_marking()) {
marking_->EnterNoMarkingScope();
ASSERT(!marking_->IsMarking() ||
@ -4963,21 +4963,18 @@ void Map::set_prototype(Object* value, WriteBarrierMode mode) {
// If the descriptor is using the empty transition array, install a new empty
// transition array that will have place for an element transition.
static MaybeObject* EnsureHasTransitionArray(Map* map) {
TransitionArray* transitions;
MaybeObject* maybe_transitions;
static void EnsureHasTransitionArray(Handle<Map> map) {
Handle<TransitionArray> transitions;
if (!map->HasTransitionArray()) {
maybe_transitions = TransitionArray::Allocate(map->GetIsolate(), 0);
if (!maybe_transitions->To(&transitions)) return maybe_transitions;
transitions = TransitionArray::Allocate(map->GetIsolate(), 0);
transitions->set_back_pointer_storage(map->GetBackPointer());
} else if (!map->transitions()->IsFullTransitionArray()) {
maybe_transitions = map->transitions()->ExtendToFullTransitionArray();
if (!maybe_transitions->To(&transitions)) return maybe_transitions;
transitions = TransitionArray::ExtendToFullTransitionArray(
handle(map->transitions()));
} else {
return map;
return;
}
map->set_transitions(transitions);
return transitions;
map->set_transitions(*transitions);
}
@ -5018,12 +5015,11 @@ void Map::ClearTransitions(Heap* heap, WriteBarrierMode mode) {
}
void Map::AppendDescriptor(Descriptor* desc,
const DescriptorArray::WhitenessWitness& witness) {
void Map::AppendDescriptor(Descriptor* desc) {
DescriptorArray* descriptors = instance_descriptors();
int number_of_own_descriptors = NumberOfOwnDescriptors();
ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
descriptors->Append(desc, witness);
descriptors->Append(desc);
SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
}
@ -5089,19 +5085,18 @@ FixedArray* Map::GetPrototypeTransitions() {
}
MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) {
MaybeObject* allow_prototype = EnsureHasTransitionArray(this);
if (allow_prototype->IsFailure()) return allow_prototype;
int old_number_of_transitions = NumberOfProtoTransitions();
void Map::SetPrototypeTransitions(
Handle<Map> map, Handle<FixedArray> proto_transitions) {
EnsureHasTransitionArray(map);
int old_number_of_transitions = map->NumberOfProtoTransitions();
#ifdef DEBUG
if (HasPrototypeTransitions()) {
ASSERT(GetPrototypeTransitions() != proto_transitions);
ZapPrototypeTransitions();
if (map->HasPrototypeTransitions()) {
ASSERT(map->GetPrototypeTransitions() != *proto_transitions);
map->ZapPrototypeTransitions();
}
#endif
transitions()->SetPrototypeTransitions(proto_transitions);
SetNumberOfProtoTransitions(old_number_of_transitions);
return this;
map->transitions()->SetPrototypeTransitions(*proto_transitions);
map->SetNumberOfProtoTransitions(old_number_of_transitions);
}

View File

@ -4696,10 +4696,136 @@ void JSObject::TransformToFastProperties(Handle<JSObject> object,
int unused_property_fields) {
if (object->HasFastProperties()) return;
ASSERT(!object->IsGlobalObject());
CALL_HEAP_FUNCTION_VOID(
object->GetIsolate(),
object->property_dictionary()->TransformPropertiesToFastFor(
*object, unused_property_fields));
Isolate* isolate = object->GetIsolate();
Factory* factory = isolate->factory();
Handle<NameDictionary> dictionary(object->property_dictionary());
// Make sure we preserve dictionary representation if there are too many
// descriptors.
int number_of_elements = dictionary->NumberOfElements();
if (number_of_elements > kMaxNumberOfDescriptors) return;
if (number_of_elements != dictionary->NextEnumerationIndex()) {
NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
}
int instance_descriptor_length = 0;
int number_of_fields = 0;
// Compute the length of the instance descriptor.
int capacity = dictionary->Capacity();
for (int i = 0; i < capacity; i++) {
Object* k = dictionary->KeyAt(i);
if (dictionary->IsKey(k)) {
Object* value = dictionary->ValueAt(i);
PropertyType type = dictionary->DetailsAt(i).type();
ASSERT(type != FIELD);
instance_descriptor_length++;
if (type == NORMAL && !value->IsJSFunction()) {
number_of_fields += 1;
}
}
}
int inobject_props = object->map()->inobject_properties();
// Allocate new map.
Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
new_map->set_dictionary_map(false);
if (instance_descriptor_length == 0) {
DisallowHeapAllocation no_gc;
ASSERT_LE(unused_property_fields, inobject_props);
// Transform the object.
new_map->set_unused_property_fields(inobject_props);
object->set_map(*new_map);
object->set_properties(isolate->heap()->empty_fixed_array());
// Check that it really works.
ASSERT(object->HasFastProperties());
return;
}
// Allocate the instance descriptor.
Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
isolate, instance_descriptor_length);
int number_of_allocated_fields =
number_of_fields + unused_property_fields - inobject_props;
if (number_of_allocated_fields < 0) {
// There is enough inobject space for all fields (including unused).
number_of_allocated_fields = 0;
unused_property_fields = inobject_props - number_of_fields;
}
// Allocate the fixed array for the fields.
Handle<FixedArray> fields = factory->NewFixedArray(
number_of_allocated_fields);
// Fill in the instance descriptor and the fields.
int current_offset = 0;
for (int i = 0; i < capacity; i++) {
Object* k = dictionary->KeyAt(i);
if (dictionary->IsKey(k)) {
Object* value = dictionary->ValueAt(i);
Handle<Name> key;
if (k->IsSymbol()) {
key = handle(Symbol::cast(k));
} else {
// Ensure the key is a unique name before writing into the
// instance descriptor.
key = factory->InternalizeString(handle(String::cast(k)));
}
PropertyDetails details = dictionary->DetailsAt(i);
int enumeration_index = details.dictionary_index();
PropertyType type = details.type();
if (value->IsJSFunction()) {
ConstantDescriptor d(key,
handle(value, isolate),
details.attributes());
descriptors->Set(enumeration_index - 1, &d);
} else if (type == NORMAL) {
if (current_offset < inobject_props) {
object->InObjectPropertyAtPut(current_offset,
value,
UPDATE_WRITE_BARRIER);
} else {
int offset = current_offset - inobject_props;
fields->set(offset, value);
}
FieldDescriptor d(key,
current_offset++,
details.attributes(),
// TODO(verwaest): value->OptimalRepresentation();
Representation::Tagged());
descriptors->Set(enumeration_index - 1, &d);
} else if (type == CALLBACKS) {
CallbacksDescriptor d(key,
handle(value, isolate),
details.attributes());
descriptors->Set(enumeration_index - 1, &d);
} else {
UNREACHABLE();
}
}
}
ASSERT(current_offset == number_of_fields);
descriptors->Sort();
DisallowHeapAllocation no_gc;
new_map->InitializeDescriptors(*descriptors);
new_map->set_unused_property_fields(unused_property_fields);
// Transform the object.
object->set_map(*new_map);
object->set_properties(*fields);
ASSERT(object->IsJSObject());
// Check that it really works.
ASSERT(object->HasFastProperties());
}
@ -6753,23 +6879,17 @@ Handle<Map> Map::CopyNormalized(Handle<Map> map,
Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
CALL_HEAP_FUNCTION(map->GetIsolate(), map->CopyDropDescriptors(), Map);
}
MaybeObject* Map::CopyDropDescriptors() {
Map* result;
MaybeObject* maybe_result = RawCopy(instance_size());
if (!maybe_result->To(&result)) return maybe_result;
Handle<Map> result = RawCopy(map, map->instance_size());
// Please note instance_type and instance_size are set when allocated.
result->set_inobject_properties(inobject_properties());
result->set_unused_property_fields(unused_property_fields());
result->set_inobject_properties(map->inobject_properties());
result->set_unused_property_fields(map->unused_property_fields());
result->set_pre_allocated_property_fields(pre_allocated_property_fields());
result->set_pre_allocated_property_fields(
map->pre_allocated_property_fields());
result->set_is_shared(false);
result->ClearCodeCache(GetHeap());
NotifyLeafMapLayoutChange();
result->ClearCodeCache(map->GetHeap());
map->NotifyLeafMapLayoutChange();
return result;
}
@ -6792,7 +6912,7 @@ Handle<Map> Map::ShareDescriptor(Handle<Map> map,
if (descriptors->NumberOfSlackDescriptors() == 0) {
int old_size = descriptors->number_of_descriptors();
if (old_size == 0) {
descriptors = map->GetIsolate()->factory()->NewDescriptorArray(0, 1);
descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
} else {
Map::EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2);
descriptors = handle(map->instance_descriptors());
@ -7060,7 +7180,7 @@ Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
int size = enumeration_index;
Handle<DescriptorArray> descriptors =
desc->GetIsolate()->factory()->NewDescriptorArray(size, slack);
DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
DescriptorArray::WhitenessWitness witness(*descriptors);
if (attributes != NONE) {
@ -7919,21 +8039,20 @@ bool FixedArray::IsEqualTo(FixedArray* other) {
#endif
MaybeObject* DescriptorArray::Allocate(Isolate* isolate,
int number_of_descriptors,
int slack) {
Heap* heap = isolate->heap();
Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
int number_of_descriptors,
int slack) {
ASSERT(0 <= number_of_descriptors);
Factory* factory = isolate->factory();
// Do not use DescriptorArray::cast on incomplete object.
int size = number_of_descriptors + slack;
if (size == 0) return heap->empty_descriptor_array();
FixedArray* result;
if (size == 0) return factory->empty_descriptor_array();
// Allocate the array of keys.
MaybeObject* maybe_array = heap->AllocateFixedArray(LengthFor(size));
if (!maybe_array->To(&result)) return maybe_array;
Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
result->set(kEnumCacheIndex, Smi::FromInt(0));
return result;
return Handle<DescriptorArray>::cast(result);
}
@ -7997,11 +8116,13 @@ Handle<DescriptorArray> DescriptorArray::Merge(Handle<Map> left_map,
// Allocate a new descriptor array large enough to hold the required
// descriptors, with minimally the exact same size as this descriptor array.
Factory* factory = left_map->GetIsolate()->factory();
Isolate* isolate = left_map->GetIsolate();
Handle<DescriptorArray> left(left_map->instance_descriptors());
Handle<DescriptorArray> right(right_map->instance_descriptors());
Handle<DescriptorArray> result = factory->NewDescriptorArray(
new_size, Max(new_size, right->number_of_descriptors()) - new_size);
Handle<DescriptorArray> result = DescriptorArray::Allocate(
isolate,
new_size,
Max(new_size, right->number_of_descriptors()) - new_size);
ASSERT(result->length() > left->length() ||
result->NumberOfSlackDescriptors() > 0 ||
result->number_of_descriptors() == right->number_of_descriptors());
@ -11476,10 +11597,7 @@ Handle<Map> Map::PutPrototypeTransition(Handle<Map> map,
Factory* factory = map->GetIsolate()->factory();
cache = factory->CopySizeFixedArray(cache, transitions * 2 * step + header);
CALL_AND_RETRY_OR_DIE(map->GetIsolate(),
map->SetPrototypeTransitions(*cache),
break,
return Handle<Map>());
Map::SetPrototypeTransitions(map, cache);
}
// Reload number of transitions as GC might shrink them.
@ -15570,151 +15688,6 @@ Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
}
MaybeObject* NameDictionary::TransformPropertiesToFastFor(
JSObject* obj, int unused_property_fields) {
// Make sure we preserve dictionary representation if there are too many
// descriptors.
int number_of_elements = NumberOfElements();
if (number_of_elements > kMaxNumberOfDescriptors) return obj;
if (number_of_elements != NextEnumerationIndex()) {
MaybeObject* maybe_result = GenerateNewEnumerationIndices();
if (maybe_result->IsFailure()) return maybe_result;
}
int instance_descriptor_length = 0;
int number_of_fields = 0;
Heap* heap = GetHeap();
// Compute the length of the instance descriptor.
int capacity = Capacity();
for (int i = 0; i < capacity; i++) {
Object* k = KeyAt(i);
if (IsKey(k)) {
Object* value = ValueAt(i);
PropertyType type = DetailsAt(i).type();
ASSERT(type != FIELD);
instance_descriptor_length++;
if (type == NORMAL && !value->IsJSFunction()) {
number_of_fields += 1;
}
}
}
int inobject_props = obj->map()->inobject_properties();
// Allocate new map.
Map* new_map;
MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors();
if (!maybe_new_map->To(&new_map)) return maybe_new_map;
new_map->set_dictionary_map(false);
if (instance_descriptor_length == 0) {
ASSERT_LE(unused_property_fields, inobject_props);
// Transform the object.
new_map->set_unused_property_fields(inobject_props);
obj->set_map(new_map);
obj->set_properties(heap->empty_fixed_array());
// Check that it really works.
ASSERT(obj->HasFastProperties());
return obj;
}
// Allocate the instance descriptor.
DescriptorArray* descriptors;
MaybeObject* maybe_descriptors =
DescriptorArray::Allocate(GetIsolate(), instance_descriptor_length);
if (!maybe_descriptors->To(&descriptors)) {
return maybe_descriptors;
}
DescriptorArray::WhitenessWitness witness(descriptors);
int number_of_allocated_fields =
number_of_fields + unused_property_fields - inobject_props;
if (number_of_allocated_fields < 0) {
// There is enough inobject space for all fields (including unused).
number_of_allocated_fields = 0;
unused_property_fields = inobject_props - number_of_fields;
}
// Allocate the fixed array for the fields.
FixedArray* fields;
MaybeObject* maybe_fields =
heap->AllocateFixedArray(number_of_allocated_fields);
if (!maybe_fields->To(&fields)) return maybe_fields;
// Fill in the instance descriptor and the fields.
int current_offset = 0;
for (int i = 0; i < capacity; i++) {
Object* k = KeyAt(i);
if (IsKey(k)) {
Object* value = ValueAt(i);
Name* key;
if (k->IsSymbol()) {
key = Symbol::cast(k);
} else {
// Ensure the key is a unique name before writing into the
// instance descriptor.
MaybeObject* maybe_key = heap->InternalizeString(String::cast(k));
if (!maybe_key->To(&key)) return maybe_key;
}
PropertyDetails details = DetailsAt(i);
int enumeration_index = details.dictionary_index();
PropertyType type = details.type();
if (value->IsJSFunction()) {
ConstantDescriptor d(handle(key),
handle(value, GetIsolate()),
details.attributes());
descriptors->Set(enumeration_index - 1, &d, witness);
} else if (type == NORMAL) {
if (current_offset < inobject_props) {
obj->InObjectPropertyAtPut(current_offset,
value,
UPDATE_WRITE_BARRIER);
} else {
int offset = current_offset - inobject_props;
fields->set(offset, value);
}
FieldDescriptor d(handle(key),
current_offset++,
details.attributes(),
// TODO(verwaest): value->OptimalRepresentation();
Representation::Tagged());
descriptors->Set(enumeration_index - 1, &d, witness);
} else if (type == CALLBACKS) {
CallbacksDescriptor d(handle(key),
handle(value, GetIsolate()),
details.attributes());
descriptors->Set(enumeration_index - 1, &d, witness);
} else {
UNREACHABLE();
}
}
}
ASSERT(current_offset == number_of_fields);
descriptors->Sort();
new_map->InitializeDescriptors(descriptors);
new_map->set_unused_property_fields(unused_property_fields);
// Transform the object.
obj->set_map(new_map);
obj->set_properties(fields);
ASSERT(obj->IsJSObject());
// Check that it really works.
ASSERT(obj->HasFastProperties());
return obj;
}
Handle<ObjectHashTable> ObjectHashTable::EnsureCapacity(
Handle<ObjectHashTable> table,
int n,

View File

@ -3349,23 +3349,6 @@ class ConstantPoolArray: public FixedArrayBase {
// [2 + number of descriptors * kDescriptorSize]: start of slack
class DescriptorArray: public FixedArray {
public:
// WhitenessWitness is used to prove that a descriptor array is white
// (unmarked), so incremental write barriers can be skipped because the
// marking invariant cannot be broken and slots pointing into evacuation
// candidates will be discovered when the object is scanned. A witness is
// always stack-allocated right after creating an array. By allocating a
// witness, incremental marking is globally disabled. The witness is then
// passed along wherever needed to statically prove that the array is known to
// be white.
class WhitenessWitness {
public:
inline explicit WhitenessWitness(FixedArray* array);
inline ~WhitenessWitness();
private:
IncrementalMarking* marking_;
};
// Returns true for both shared empty_descriptor_array and for smis, which the
// map uses to encode additional bit fields when the descriptor array is not
// yet used.
@ -3455,15 +3438,12 @@ class DescriptorArray: public FixedArray {
// Accessor for complete descriptor.
inline void Get(int descriptor_number, Descriptor* desc);
inline void Set(int descriptor_number,
Descriptor* desc,
const WhitenessWitness&);
inline void Set(int descriptor_number, Descriptor* desc);
void Replace(int descriptor_number, Descriptor* descriptor);
// Append automatically sets the enumeration index. This should only be used
// to add descriptors in bulk at the end, followed by sorting the descriptor
// array.
inline void Append(Descriptor* desc, const WhitenessWitness&);
inline void Append(Descriptor* desc);
static Handle<DescriptorArray> Merge(Handle<Map> left_map,
@ -3502,9 +3482,9 @@ class DescriptorArray: public FixedArray {
// Allocates a DescriptorArray, but returns the singleton
// empty descriptor array object if number_of_descriptors is 0.
MUST_USE_RESULT static MaybeObject* Allocate(Isolate* isolate,
int number_of_descriptors,
int slack = 0);
static Handle<DescriptorArray> Allocate(Isolate* isolate,
int number_of_descriptors,
int slack = 0);
// Casting.
static inline DescriptorArray* cast(Object* obj);
@ -3558,6 +3538,23 @@ class DescriptorArray: public FixedArray {
}
private:
// WhitenessWitness is used to prove that a descriptor array is white
// (unmarked), so incremental write barriers can be skipped because the
// marking invariant cannot be broken and slots pointing into evacuation
// candidates will be discovered when the object is scanned. A witness is
// always stack-allocated right after creating an array. By allocating a
// witness, incremental marking is globally disabled. The witness is then
// passed along wherever needed to statically prove that the array is known to
// be white.
class WhitenessWitness {
public:
inline explicit WhitenessWitness(DescriptorArray* array);
inline ~WhitenessWitness();
private:
IncrementalMarking* marking_;
};
// An entry in a DescriptorArray, represented as an (array, index) pair.
class Entry {
public:
@ -3597,7 +3594,11 @@ class DescriptorArray: public FixedArray {
DescriptorArray* src,
const WhitenessWitness&);
inline void Set(int descriptor_number, Descriptor* desc);
inline void Set(int descriptor_number,
Descriptor* desc,
const WhitenessWitness&);
inline void Append(Descriptor* desc, const WhitenessWitness&);
// Swap first and second descriptor.
inline void SwapSortedKeys(int first, int second);
@ -4099,11 +4100,6 @@ class NameDictionary: public Dictionary<NameDictionaryShape, Name*> {
static void DoGenerateNewEnumerationIndices(
Handle<NameDictionary> dictionary);
// For transforming properties of a JSObject.
MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor(
JSObject* obj,
int unused_property_fields);
// Find entry for key, otherwise return kNotFound. Optimized version of
// HashTable::FindEntry.
int FindEntry(Name* key);
@ -6336,8 +6332,8 @@ class Map: public HeapObject {
// 2 + 2 * i: prototype
// 3 + 2 * i: target map
inline FixedArray* GetPrototypeTransitions();
MUST_USE_RESULT inline MaybeObject* SetPrototypeTransitions(
FixedArray* prototype_transitions);
static inline void SetPrototypeTransitions(
Handle<Map> map, Handle<FixedArray> prototype_transitions);
inline bool HasPrototypeTransitions();
static const int kProtoTransitionHeaderSize = 1;
@ -6432,7 +6428,6 @@ class Map: public HeapObject {
static Handle<Map> RawCopy(Handle<Map> map, int instance_size);
MUST_USE_RESULT MaybeObject* RawCopy(int instance_size);
static Handle<Map> CopyDropDescriptors(Handle<Map> map);
MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
static Handle<Map> CopyReplaceDescriptors(
Handle<Map> map,
Handle<DescriptorArray> descriptors,
@ -6476,8 +6471,7 @@ class Map: public HeapObject {
PropertyNormalizationMode mode,
NormalizedMapSharingMode sharing);
inline void AppendDescriptor(Descriptor* desc,
const DescriptorArray::WhitenessWitness&);
inline void AppendDescriptor(Descriptor* desc);
// Returns a copy of the map, with all transitions dropped from the
// instance descriptors.

View File

@ -35,34 +35,21 @@ namespace v8 {
namespace internal {
static MaybeObject* AllocateRaw(Isolate* isolate, int length) {
// Use FixedArray to not use TransitionArray::cast on incomplete object.
FixedArray* array;
MaybeObject* maybe_array = isolate->heap()->AllocateFixedArray(length);
if (!maybe_array->To(&array)) return maybe_array;
return array;
}
MaybeObject* TransitionArray::Allocate(Isolate* isolate,
int number_of_transitions) {
FixedArray* array;
MaybeObject* maybe_array =
AllocateRaw(isolate, ToKeyIndex(number_of_transitions));
if (!maybe_array->To(&array)) return maybe_array;
Handle<TransitionArray> TransitionArray::Allocate(Isolate* isolate,
int number_of_transitions) {
Handle<FixedArray> array =
isolate->factory()->NewFixedArray(ToKeyIndex(number_of_transitions));
array->set(kPrototypeTransitionsIndex, Smi::FromInt(0));
return array;
return Handle<TransitionArray>::cast(array);
}
MaybeObject* TransitionArray::AllocateSimple(Isolate* isolate,
Map* target) {
FixedArray* array;
MaybeObject* maybe_array =
AllocateRaw(isolate, kSimpleTransitionSize);
if (!maybe_array->To(&array)) return maybe_array;
array->set(kSimpleTransitionTarget, target);
return array;
Handle<TransitionArray> TransitionArray::AllocateSimple(Isolate* isolate,
Handle<Map> target) {
Handle<FixedArray> array =
isolate->factory()->NewFixedArray(kSimpleTransitionSize);
array->set(kSimpleTransitionTarget, *target);
return Handle<TransitionArray>::cast(array);
}
@ -85,12 +72,12 @@ Handle<TransitionArray> TransitionArray::NewWith(Handle<Map> map,
Handle<Map> target,
SimpleTransitionFlag flag) {
Handle<TransitionArray> result;
Factory* factory = name->GetIsolate()->factory();
Isolate* isolate = name->GetIsolate();
if (flag == SIMPLE_TRANSITION) {
result = factory->NewSimpleTransitionArray(target);
result = AllocateSimple(isolate, target);
} else {
result = factory->NewTransitionArray(1);
result = Allocate(isolate, 1);
result->NoIncrementalWriteBarrierSet(0, *name, *target);
}
result->set_back_pointer_storage(map->GetBackPointer());
@ -98,18 +85,18 @@ Handle<TransitionArray> TransitionArray::NewWith(Handle<Map> map,
}
MaybeObject* TransitionArray::ExtendToFullTransitionArray() {
ASSERT(!IsFullTransitionArray());
int nof = number_of_transitions();
TransitionArray* result;
MaybeObject* maybe_result = Allocate(GetIsolate(), nof);
if (!maybe_result->To(&result)) return maybe_result;
Handle<TransitionArray> TransitionArray::ExtendToFullTransitionArray(
Handle<TransitionArray> array) {
ASSERT(!array->IsFullTransitionArray());
int nof = array->number_of_transitions();
Handle<TransitionArray> result = Allocate(array->GetIsolate(), nof);
if (nof == 1) {
result->NoIncrementalWriteBarrierCopyFrom(this, kSimpleTransitionIndex, 0);
result->NoIncrementalWriteBarrierCopyFrom(
*array, kSimpleTransitionIndex, 0);
}
result->set_back_pointer_storage(back_pointer_storage());
result->set_back_pointer_storage(array->back_pointer_storage());
return result;
}
@ -128,8 +115,7 @@ Handle<TransitionArray> TransitionArray::CopyInsert(Handle<Map> map,
int insertion_index = map->transitions()->Search(*name);
if (insertion_index == kNotFound) ++new_size;
Handle<TransitionArray> result =
map->GetIsolate()->factory()->NewTransitionArray(new_size);
Handle<TransitionArray> result = Allocate(map->GetIsolate(), new_size);
// The map's transition array may have disappeared or grown smaller during
// the allocation above as it was weakly traversed. Trim the result copy if

View File

@ -95,13 +95,8 @@ class TransitionArray: public FixedArray {
inline int number_of_entries() { return number_of_transitions(); }
// Allocate a new transition array with a single entry.
static Handle<TransitionArray> NewWith(Handle<Map> map,
Handle<Name> name,
Handle<Map> target,
SimpleTransitionFlag flag);
MUST_USE_RESULT MaybeObject* ExtendToFullTransitionArray();
static Handle<TransitionArray> ExtendToFullTransitionArray(
Handle<TransitionArray> array);
// Create a transition array, copying from the owning map if it already has
// one, otherwise creating a new one according to flag.
@ -112,21 +107,13 @@ class TransitionArray: public FixedArray {
Handle<Map> target,
SimpleTransitionFlag flag);
// Copy a single transition from the origin array.
inline void NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
int origin_transition,
int target_transition);
// Search a transition for a given property name.
inline int Search(Name* name);
// Allocates a TransitionArray.
MUST_USE_RESULT static MaybeObject* Allocate(
static Handle<TransitionArray> Allocate(
Isolate* isolate, int number_of_transitions);
MUST_USE_RESULT static MaybeObject* AllocateSimple(
Isolate* isolate, Map* target);
bool IsSimpleTransition() {
return length() == kSimpleTransitionSize &&
get(kSimpleTransitionTarget)->IsHeapObject() &&
@ -204,10 +191,24 @@ class TransitionArray: public FixedArray {
kTransitionTarget;
}
static Handle<TransitionArray> AllocateSimple(
Isolate* isolate, Handle<Map> target);
// Allocate a new transition array with a single entry.
static Handle<TransitionArray> NewWith(Handle<Map> map,
Handle<Name> name,
Handle<Map> target,
SimpleTransitionFlag flag);
inline void NoIncrementalWriteBarrierSet(int transition_number,
Name* key,
Map* target);
// Copy a single transition from the origin array.
inline void NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
int origin_transition,
int target_transition);
DISALLOW_IMPLICIT_CONSTRUCTORS(TransitionArray);
};

View File

@ -137,15 +137,12 @@ TEST(StressJS) {
factory->NewStringFromAscii(Vector<const char>("get", 3));
ASSERT(instance_descriptors->IsEmpty());
Handle<DescriptorArray> new_descriptors = factory->NewDescriptorArray(0, 1);
v8::internal::DescriptorArray::WhitenessWitness witness(*new_descriptors);
map->set_instance_descriptors(*new_descriptors);
Map::EnsureDescriptorSlack(map, 1);
CallbacksDescriptor d(name,
foreign,
static_cast<PropertyAttributes>(0));
map->AppendDescriptor(&d, witness);
map->AppendDescriptor(&d);
// Add the Foo constructor the global object.
env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "Foo"),