Commit d296a229 authored by bak@chromium.org's avatar bak@chromium.org

- Fixed performance regression caused by ComputeContextSlotReceiver.

- Eliminated a few write barriers.

Review URL: http://codereview.chromium.org/8103

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@573 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e1c2887a
...@@ -1378,12 +1378,11 @@ Object* Heap::AllocateConsString(String* first, String* second) { ...@@ -1378,12 +1378,11 @@ Object* Heap::AllocateConsString(String* first, String* second) {
Object* result = Allocate(map, NEW_SPACE); Object* result = Allocate(map, NEW_SPACE);
if (result->IsFailure()) return result; if (result->IsFailure()) return result;
ASSERT(InNewSpace(result));
ConsString* cons_string = ConsString::cast(result); ConsString* cons_string = ConsString::cast(result);
cons_string->set_first(first); cons_string->set_first(first, SKIP_WRITE_BARRIER);
cons_string->set_second(second); cons_string->set_second(second, SKIP_WRITE_BARRIER);
cons_string->set_length(length); cons_string->set_length(length);
return result; return result;
} }
...@@ -1615,7 +1614,7 @@ Object* Heap::InitializeFunction(JSFunction* function, ...@@ -1615,7 +1614,7 @@ Object* Heap::InitializeFunction(JSFunction* function,
function->set_shared(shared); function->set_shared(shared);
function->set_prototype_or_initial_map(prototype); function->set_prototype_or_initial_map(prototype);
function->set_context(undefined_value()); function->set_context(undefined_value());
function->set_literals(empty_fixed_array()); function->set_literals(empty_fixed_array(), SKIP_WRITE_BARRIER);
return function; return function;
} }
...@@ -1676,14 +1675,6 @@ Object* Heap::AllocateArgumentsObject(Object* callee, int length) { ...@@ -1676,14 +1675,6 @@ Object* Heap::AllocateArgumentsObject(Object* callee, int length) {
Smi::FromInt(length), Smi::FromInt(length),
SKIP_WRITE_BARRIER); SKIP_WRITE_BARRIER);
// Allocate the elements if needed.
if (length > 0) {
// Allocate the fixed array.
Object* obj = Heap::AllocateFixedArray(length);
if (obj->IsFailure()) return obj;
JSObject::cast(result)->set_elements(FixedArray::cast(obj));
}
// Check the state of the object // Check the state of the object
ASSERT(JSObject::cast(result)->HasFastProperties()); ASSERT(JSObject::cast(result)->HasFastProperties());
ASSERT(JSObject::cast(result)->HasFastElements()); ASSERT(JSObject::cast(result)->HasFastElements());
......
...@@ -741,6 +741,9 @@ class Heap : public AllStatic { ...@@ -741,6 +741,9 @@ class Heap : public AllStatic {
return amount_of_external_allocated_memory_; return amount_of_external_allocated_memory_;
} }
// Allocate unitialized fixed array (pretenure == NON_TENURE).
static Object* AllocateRawFixedArray(int length);
private: private:
static int semispace_size_; static int semispace_size_;
static int initial_semispace_size_; static int initial_semispace_size_;
...@@ -835,9 +838,6 @@ class Heap : public AllStatic { ...@@ -835,9 +838,6 @@ class Heap : public AllStatic {
// (since both AllocateRaw and AllocateRawMap are inlined). // (since both AllocateRaw and AllocateRawMap are inlined).
static inline Object* AllocateRawMap(int size_in_bytes); static inline Object* AllocateRawMap(int size_in_bytes);
// Allocate unitialized fixed array (pretenure == NON_TENURE).
static Object* AllocateRawFixedArray(int length);
// Initializes a JSObject based on its map. // Initializes a JSObject based on its map.
static void InitializeJSObjectFromMap(JSObject* obj, static void InitializeJSObjectFromMap(JSObject* obj,
FixedArray* properties, FixedArray* properties,
......
...@@ -510,7 +510,7 @@ Object* Object::GetProperty(String* key, PropertyAttributes* attributes) { ...@@ -510,7 +510,7 @@ Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
#define WRITE_BARRIER(object, offset) \ #define WRITE_BARRIER(object, offset) \
Heap::RecordWrite(object->address(), offset); Heap::RecordWrite(object->address(), offset);
// CONITIONAL_WRITE_BARRIER must be issued after the actual // CONDITIONAL_WRITE_BARRIER must be issued after the actual
// write due to the assert validating the written value. // write due to the assert validating the written value.
#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \ #define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
if (mode == UPDATE_WRITE_BARRIER) { \ if (mode == UPDATE_WRITE_BARRIER) { \
...@@ -1534,9 +1534,9 @@ Object* ConsString::first() { ...@@ -1534,9 +1534,9 @@ Object* ConsString::first() {
} }
void ConsString::set_first(Object* value) { void ConsString::set_first(Object* value, WriteBarrierMode mode) {
WRITE_FIELD(this, kFirstOffset, value); WRITE_FIELD(this, kFirstOffset, value);
WRITE_BARRIER(this, kFirstOffset); CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
} }
...@@ -1545,9 +1545,9 @@ Object* ConsString::second() { ...@@ -1545,9 +1545,9 @@ Object* ConsString::second() {
} }
void ConsString::set_second(Object* value) { void ConsString::set_second(Object* value, WriteBarrierMode mode) {
WRITE_FIELD(this, kSecondOffset, value); WRITE_FIELD(this, kSecondOffset, value);
WRITE_BARRIER(this, kSecondOffset); CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
} }
...@@ -2071,6 +2071,11 @@ bool JSFunction::is_compiled() { ...@@ -2071,6 +2071,11 @@ bool JSFunction::is_compiled() {
} }
int JSFunction::NumberOfLiterals() {
return literals()->length();
}
Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) { Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
ASSERT(0 <= id && id < kJSBuiltinsCount); ASSERT(0 <= id && id < kJSBuiltinsCount);
return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize)); return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
...@@ -2351,7 +2356,7 @@ void Map::ClearCodeCache() { ...@@ -2351,7 +2356,7 @@ void Map::ClearCodeCache() {
void JSArray::SetContent(FixedArray* storage) { void JSArray::SetContent(FixedArray* storage) {
set_length(Smi::FromInt(storage->length())); set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
set_elements(storage); set_elements(storage);
} }
......
...@@ -2580,14 +2580,15 @@ Object* FixedArray::UnionOfKeys(FixedArray* other) { ...@@ -2580,14 +2580,15 @@ Object* FixedArray::UnionOfKeys(FixedArray* other) {
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
// Fill in the content // Fill in the content
FixedArray* result = FixedArray::cast(obj); FixedArray* result = FixedArray::cast(obj);
WriteBarrierMode mode = result->GetWriteBarrierMode();
for (int i = 0; i < len0; i++) { for (int i = 0; i < len0; i++) {
result->set(i, get(i)); result->set(i, get(i), mode);
} }
// Fill in the extra keys. // Fill in the extra keys.
int index = 0; int index = 0;
for (int y = 0; y < len1; y++) { for (int y = 0; y < len1; y++) {
if (!HasKey(this, other->get(y))) { if (!HasKey(this, other->get(y))) {
result->set(len0 + index, other->get(y)); result->set(len0 + index, other->get(y), mode);
index++; index++;
} }
} }
...@@ -2601,14 +2602,14 @@ Object* FixedArray::CopySize(int new_length) { ...@@ -2601,14 +2602,14 @@ Object* FixedArray::CopySize(int new_length) {
Object* obj = Heap::AllocateFixedArray(new_length); Object* obj = Heap::AllocateFixedArray(new_length);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
FixedArray* result = FixedArray::cast(obj); FixedArray* result = FixedArray::cast(obj);
WriteBarrierMode mode = result->GetWriteBarrierMode();
// Copy the content // Copy the content
int len = length(); int len = length();
if (new_length < len) len = new_length; if (new_length < len) len = new_length;
result->set_map(map());
WriteBarrierMode mode = result->GetWriteBarrierMode();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
result->set(i, get(i), mode); result->set(i, get(i), mode);
} }
result->set_map(map());
return result; return result;
} }
...@@ -4047,11 +4048,6 @@ void Map::MapIterateBody(ObjectVisitor* v) { ...@@ -4047,11 +4048,6 @@ void Map::MapIterateBody(ObjectVisitor* v) {
} }
int JSFunction::NumberOfLiterals() {
return literals()->length();
}
Object* JSFunction::SetInstancePrototype(Object* value) { Object* JSFunction::SetInstancePrototype(Object* value) {
ASSERT(value->IsJSObject()); ASSERT(value->IsJSObject());
...@@ -5974,7 +5970,7 @@ Object* LookupCache::Put(Map* map, String* name, int value) { ...@@ -5974,7 +5970,7 @@ Object* LookupCache::Put(Map* map, String* name, int value) {
int entry = cache->FindInsertionEntry(k, key.Hash()); int entry = cache->FindInsertionEntry(k, key.Hash());
int index = EntryToIndex(entry); int index = EntryToIndex(entry);
cache->set(index, k); cache->set(index, k);
cache->set(index + 1, Smi::FromInt(value)); cache->set(index + 1, Smi::FromInt(value), SKIP_WRITE_BARRIER);
cache->ElementAdded(); cache->ElementAdded();
return cache; return cache;
} }
......
...@@ -1601,7 +1601,6 @@ class DescriptorArray: public FixedArray { ...@@ -1601,7 +1601,6 @@ class DescriptorArray: public FixedArray {
inline void Get(int descriptor_number, Descriptor* desc); inline void Get(int descriptor_number, Descriptor* desc);
inline void Set(int descriptor_number, Descriptor* desc); inline void Set(int descriptor_number, Descriptor* desc);
// Copy the descriptor array, insert a new descriptor and optionally // Copy the descriptor array, insert a new descriptor and optionally
// remove map transitions. If the descriptor is already present, it is // remove map transitions. If the descriptor is already present, it is
// replaced. If a replaced descriptor is a real property (not a transition // replaced. If a replaced descriptor is a real property (not a transition
...@@ -2750,7 +2749,7 @@ class JSFunction: public JSObject { ...@@ -2750,7 +2749,7 @@ class JSFunction: public JSObject {
#endif #endif
// Returns the number of allocated literals. // Returns the number of allocated literals.
int NumberOfLiterals(); inline int NumberOfLiterals();
// Retrieve the global context from a function's literal array. // Retrieve the global context from a function's literal array.
static Context* GlobalContextFromLiterals(FixedArray* literals); static Context* GlobalContextFromLiterals(FixedArray* literals);
...@@ -3347,11 +3346,13 @@ class ConsString: public String { ...@@ -3347,11 +3346,13 @@ class ConsString: public String {
public: public:
// First object of the cons cell. // First object of the cons cell.
inline Object* first(); inline Object* first();
inline void set_first(Object* first); inline void set_first(Object* first,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Second object of the cons cell. // Second object of the cons cell.
inline Object* second(); inline Object* second();
inline void set_second(Object* second); inline void set_second(Object* second,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Dispatched behavior. // Dispatched behavior.
uint16_t ConsStringGet(int index); uint16_t ConsStringGet(int index);
......
...@@ -928,7 +928,7 @@ static Object* Runtime_SetCode(Arguments args) { ...@@ -928,7 +928,7 @@ static Object* Runtime_SetCode(Arguments args) {
literals->set(JSFunction::kLiteralGlobalContextIndex, literals->set(JSFunction::kLiteralGlobalContextIndex,
context->global_context()); context->global_context());
} }
target->set_literals(*literals); target->set_literals(*literals, SKIP_WRITE_BARRIER);
} }
target->set_context(*context); target->set_context(*context);
...@@ -3134,11 +3134,16 @@ static Object* Runtime_NewArguments(Arguments args) { ...@@ -3134,11 +3134,16 @@ static Object* Runtime_NewArguments(Arguments args) {
const int length = frame->GetProvidedParametersCount(); const int length = frame->GetProvidedParametersCount();
Object* result = Heap::AllocateArgumentsObject(callee, length); Object* result = Heap::AllocateArgumentsObject(callee, length);
if (result->IsFailure()) return result; if (result->IsFailure()) return result;
FixedArray* array = FixedArray::cast(JSObject::cast(result)->elements()); if (length > 0) {
ASSERT(array->length() == length); Object* obj = Heap::AllocateFixedArray(length);
WriteBarrierMode mode = array->GetWriteBarrierMode(); if (obj->IsFailure()) return obj;
for (int i = 0; i < length; i++) { FixedArray* array = FixedArray::cast(obj);
array->set(i, frame->GetParameter(i), mode); ASSERT(array->length() == length);
WriteBarrierMode mode = array->GetWriteBarrierMode();
for (int i = 0; i < length; i++) {
array->set(i, frame->GetParameter(i), mode);
}
JSObject::cast(result)->set_elements(array);
} }
return result; return result;
} }
...@@ -3154,11 +3159,22 @@ static Object* Runtime_NewArgumentsFast(Arguments args) { ...@@ -3154,11 +3159,22 @@ static Object* Runtime_NewArgumentsFast(Arguments args) {
Object* result = Heap::AllocateArgumentsObject(callee, length); Object* result = Heap::AllocateArgumentsObject(callee, length);
if (result->IsFailure()) return result; if (result->IsFailure()) return result;
FixedArray* array = FixedArray::cast(JSObject::cast(result)->elements()); ASSERT(Heap::InNewSpace(result));
ASSERT(array->length() == length);
WriteBarrierMode mode = array->GetWriteBarrierMode(); // Allocate the elements if needed.
for (int i = 0; i < length; i++) { if (length > 0) {
array->set(i, *--parameters, mode); // Allocate the fixed array.
Object* obj = Heap::AllocateRawFixedArray(length);
if (obj->IsFailure()) return obj;
reinterpret_cast<Array*>(obj)->set_map(Heap::fixed_array_map());
FixedArray* array = FixedArray::cast(obj);
array->set_length(length);
WriteBarrierMode mode = array->GetWriteBarrierMode();
for (int i = 0; i < length; i++) {
array->set(i, *--parameters, mode);
}
JSObject::cast(result)->set_elements(FixedArray::cast(obj),
SKIP_WRITE_BARRIER);
} }
return result; return result;
} }
...@@ -3366,10 +3382,17 @@ static Object* ComputeContextSlotReceiver(Object* holder) { ...@@ -3366,10 +3382,17 @@ static Object* ComputeContextSlotReceiver(Object* holder) {
// If the "property" we were looking for is a local variable or an // If the "property" we were looking for is a local variable or an
// argument in a context, the receiver is the global object; see // argument in a context, the receiver is the global object; see
// ECMA-262, 3rd., 10.1.6 and 10.2.3. // ECMA-262, 3rd., 10.1.6 and 10.2.3.
HeapObject* object = HeapObject::cast(holder); // Contexts and global objects are most common.
Context* top = Top::context(); if (holder->IsContext()) {
if (holder->IsContext()) return top->global()->global_receiver(); return Context::cast(holder)->global()->global_receiver();
}
if (holder->IsGlobalObject()) {
// If the holder is a global object, we have to be careful to wrap
// it in its proxy if necessary.
return GlobalObject::cast(holder)->global_receiver();
}
Context* top = Top::context();
// TODO(125): Find a better - and faster way - of checking for // TODO(125): Find a better - and faster way - of checking for
// arguments and context extension objects. This kinda sucks. // arguments and context extension objects. This kinda sucks.
JSFunction* context_extension_function = JSFunction* context_extension_function =
...@@ -3386,13 +3409,7 @@ static Object* ComputeContextSlotReceiver(Object* holder) { ...@@ -3386,13 +3409,7 @@ static Object* ComputeContextSlotReceiver(Object* holder) {
return Top::context()->global()->global_receiver(); return Top::context()->global()->global_receiver();
} }
// If the holder is a global object, we have to be careful to wrap return holder;
// it in its proxy if necessary.
if (object->IsGlobalObject()) {
return GlobalObject::cast(object)->global_receiver();
} else {
return object;
}
} }
...@@ -4900,13 +4917,13 @@ static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame, ...@@ -4900,13 +4917,13 @@ static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
} }
const int length = frame->GetProvidedParametersCount(); const int length = frame->GetProvidedParametersCount();
Handle<Object> arguments = Factory::NewArgumentsObject(function, length); Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length);
FixedArray* array = FixedArray::cast(JSObject::cast(*arguments)->elements()); Handle<FixedArray> array = Factory::NewFixedArray(length);
ASSERT(array->length() == length);
WriteBarrierMode mode = array->GetWriteBarrierMode(); WriteBarrierMode mode = array->GetWriteBarrierMode();
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
array->set(i, frame->GetParameter(i), mode); array->set(i, frame->GetParameter(i), mode);
} }
arguments->set_elements(*array);
return arguments; return arguments;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment