Revision: 8815
Author: [email protected]
Date: Wed Aug 3 05:42:04 2011
Log: Fix performance regression due to elements refactor
Consolidate the runtime logic for fetching elements from Objects and
JSObjects so that element access in the GetElement cases that are not
handled in generated code.
[email protected]
BUG=none
TEST=closure.js test faster
Review URL: http://codereview.chromium.org/7569001
http://code.google.com/p/v8/source/detail?r=8815
Modified:
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
=======================================
--- /branches/bleeding_edge/src/objects.cc Wed Aug 3 04:55:13 2011
+++ /branches/bleeding_edge/src/objects.cc Wed Aug 3 05:42:04 2011
@@ -603,36 +603,68 @@
MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t
index) {
- Object* holder = NULL;
- if (IsSmi()) {
- Context* global_context =
Isolate::Current()->context()->global_context();
- holder = global_context->number_function()->instance_prototype();
- } else {
- HeapObject* heap_object = HeapObject::cast(this);
-
- if (heap_object->IsJSObject()) {
- return JSObject::cast(this)->GetElementWithReceiver(receiver, index);
- }
- Heap* heap = heap_object->GetHeap();
- Isolate* isolate = heap->isolate();
-
- Context* global_context = isolate->context()->global_context();
- if (heap_object->IsString()) {
- holder = global_context->string_function()->instance_prototype();
- } else if (heap_object->IsHeapNumber()) {
+ Heap* heap = IsSmi()
+ ? Isolate::Current()->heap()
+ : HeapObject::cast(this)->GetHeap();
+ Object* holder = this;
+
+ // Iterate up the prototype chain until an element is found or the null
+ // prototype is encountered.
+ for (holder = this;
+ holder != heap->null_value();
+ holder = holder->GetPrototype()) {
+ if (holder->IsSmi()) {
+ Context* global_context =
Isolate::Current()->context()->global_context();
holder = global_context->number_function()->instance_prototype();
- } else if (heap_object->IsBoolean()) {
- holder = global_context->boolean_function()->instance_prototype();
- } else if (heap_object->IsJSProxy()) {
- return heap->undefined_value(); // For now...
} else {
- // Undefined and null have no indexed properties.
- ASSERT(heap_object->IsUndefined() || heap_object->IsNull());
- return heap->undefined_value();
+ HeapObject* heap_object = HeapObject::cast(holder);
+ if (!heap_object->IsJSObject()) {
+ Isolate* isolate = heap->isolate();
+ Context* global_context = isolate->context()->global_context();
+ if (heap_object->IsString()) {
+ holder = global_context->string_function()->instance_prototype();
+ } else if (heap_object->IsHeapNumber()) {
+ holder = global_context->number_function()->instance_prototype();
+ } else if (heap_object->IsBoolean()) {
+ holder =
global_context->boolean_function()->instance_prototype();
+ } else if (heap_object->IsJSProxy()) {
+ return heap->undefined_value(); // For now...
+ } else {
+ // Undefined and null have no indexed properties.
+ ASSERT(heap_object->IsUndefined() || heap_object->IsNull());
+ return heap->undefined_value();
+ }
+ }
+ }
+
+ // Inline the case for JSObjects. Doing so significantly improves the
+ // performance of fetching elements where checking the prototype chain
is
+ // necessary.
+ JSObject* js_object = JSObject::cast(holder);
+
+ // Check access rights if needed.
+ if (js_object->IsAccessCheckNeeded()) {
+ Isolate* isolate = heap->isolate();
+ if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
+ isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
+ return heap->undefined_value();
+ }
+ }
+
+ if (js_object->HasIndexedInterceptor()) {
+ return js_object->GetElementWithInterceptor(receiver, index);
+ }
+
+ if (js_object->elements() != heap->empty_fixed_array()) {
+ MaybeObject* result =
js_object->GetElementsAccessor()->GetWithReceiver(
+ js_object,
+ receiver,
+ index);
+ if (result != heap->the_hole_value()) return result;
}
}
- return JSObject::cast(holder)->GetElementWithReceiver(receiver, index);
+ return heap->undefined_value();
}
@@ -8993,35 +9025,6 @@
if (pt == heap->null_value()) return heap->undefined_value();
return pt->GetElementWithReceiver(*this_handle, index);
}
-
-
-MaybeObject* JSObject::GetElementWithReceiver(Object* receiver,
- uint32_t index) {
- // Check access rights if needed.
- if (IsAccessCheckNeeded()) {
- Heap* heap = GetHeap();
- if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_GET)) {
- heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET);
- return heap->undefined_value();
- }
- }
-
- if (HasIndexedInterceptor()) {
- return GetElementWithInterceptor(receiver, index);
- }
-
- Heap* heap = GetHeap();
- if (elements() != heap->empty_fixed_array()) {
- MaybeObject* result = GetElementsAccessor()->GetWithReceiver(this,
- receiver,
- index);
- if (result != heap->the_hole_value()) return result;
- }
-
- Object* pt = GetPrototype();
- if (pt == heap->null_value()) return heap->undefined_value();
- return pt->GetElementWithReceiver(receiver, index);
-}
bool JSObject::HasDenseElements() {
=======================================
--- /branches/bleeding_edge/src/objects.h Wed Aug 3 04:55:13 2011
+++ /branches/bleeding_edge/src/objects.h Wed Aug 3 05:42:04 2011
@@ -1739,7 +1739,6 @@
// Returns the index'th element.
// The undefined object if index is out of bounds.
- MaybeObject* GetElementWithReceiver(Object* receiver, uint32_t index);
MaybeObject* GetElementWithInterceptor(Object* receiver, uint32_t index);
// Replace the elements' backing store with fast elements of the given
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev