Revision: 16930
Author: [email protected]
Date: Wed Sep 25 08:19:35 2013 UTC
Log: Speed up ArrayBuffer/typed array/DataView properties.
Optimizes byteLength, byteOffset, buffer and other properties on
ArrayBuffer, typed arrays and DataView into simple field loads. Some
unification with the way Array.length and String.length are treated.
[email protected]
Review URL: https://codereview.chromium.org/24360019
http://code.google.com/p/v8/source/detail?r=16930
Modified:
/branches/bleeding_edge/src/accessors.cc
/branches/bleeding_edge/src/accessors.h
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/src/hydrogen-instructions.h
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/hydrogen.h
/branches/bleeding_edge/src/ic.cc
=======================================
--- /branches/bleeding_edge/src/accessors.cc Thu Sep 12 13:27:42 2013 UTC
+++ /branches/bleeding_edge/src/accessors.cc Wed Sep 25 08:19:35 2013 UTC
@@ -76,6 +76,61 @@
// read-only properties must be silently ignored.
return value;
}
+
+
+static V8_INLINE bool CheckForName(Handle<String> name,
+ String* property_name,
+ int offset,
+ int* object_offset) {
+ if (name->Equals(property_name)) {
+ *object_offset = offset;
+ return true;
+ }
+ return false;
+}
+
+
+bool Accessors::IsJSObjectFieldAccessor(
+ Handle<Map> map, Handle<String> name,
+ int* object_offset) {
+ Isolate* isolate = map->GetIsolate();
+ switch (map->instance_type()) {
+ case JS_ARRAY_TYPE:
+ return
+ CheckForName(name, isolate->heap()->length_string(),
+ JSArray::kLengthOffset, object_offset);
+ case JS_TYPED_ARRAY_TYPE:
+ return
+ CheckForName(name, isolate->heap()->length_string(),
+ JSTypedArray::kLengthOffset, object_offset) ||
+ CheckForName(name, isolate->heap()->byte_length_string(),
+ JSTypedArray::kByteLengthOffset, object_offset) ||
+ CheckForName(name, isolate->heap()->byte_offset_string(),
+ JSTypedArray::kByteOffsetOffset, object_offset) ||
+ CheckForName(name, isolate->heap()->buffer_string(),
+ JSTypedArray::kBufferOffset, object_offset);
+ case JS_ARRAY_BUFFER_TYPE:
+ return
+ CheckForName(name, isolate->heap()->byte_length_string(),
+ JSArrayBuffer::kByteLengthOffset, object_offset);
+ case JS_DATA_VIEW_TYPE:
+ return
+ CheckForName(name, isolate->heap()->byte_length_string(),
+ JSDataView::kByteLengthOffset, object_offset) ||
+ CheckForName(name, isolate->heap()->byte_offset_string(),
+ JSDataView::kByteOffsetOffset, object_offset) ||
+ CheckForName(name, isolate->heap()->buffer_string(),
+ JSDataView::kBufferOffset, object_offset);
+ default: {
+ if (map->instance_type() < FIRST_NONSTRING_TYPE) {
+ return
+ CheckForName(name, isolate->heap()->length_string(),
+ String::kLengthOffset, object_offset);
+ }
+ return false;
+ }
+ }
+}
//
=======================================
--- /branches/bleeding_edge/src/accessors.h Mon Sep 2 09:25:20 2013 UTC
+++ /branches/bleeding_edge/src/accessors.h Wed Sep 25 08:19:35 2013 UTC
@@ -86,6 +86,13 @@
static Handle<AccessorInfo> MakeModuleExport(
Handle<String> name, int index, PropertyAttributes attributes);
+ // Returns true for properties that are accessors to object fields.
+ // If true, *object_offset contains offset of object field.
+ static bool IsJSObjectFieldAccessor(
+ Handle<Map> map, Handle<String> name,
+ int* object_offset);
+
+
private:
// Accessor functions only used through the descriptor.
static MaybeObject* FunctionSetPrototype(Isolate* isolate,
=======================================
--- /branches/bleeding_edge/src/heap.h Mon Sep 23 14:48:49 2013 UTC
+++ /branches/bleeding_edge/src/heap.h Wed Sep 25 08:19:35 2013 UTC
@@ -292,7 +292,10 @@
V(throw_string, "throw") \
V(done_string, "done") \
V(value_string, "value") \
- V(next_string, "next")
+ V(next_string, "next") \
+ V(byte_length_string, "byteLength") \
+ V(byte_offset_string, "byteOffset") \
+ V(buffer_string, "buffer")
// Forward declarations.
class GCTracer;
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Tue Sep 24 10:30:41
2013 UTC
+++ /branches/bleeding_edge/src/hydrogen-instructions.h Wed Sep 25 08:19:35
2013 UTC
@@ -5625,13 +5625,6 @@
FLAG_track_fields
? Representation::Smi() : Representation::Tagged());
}
-
- static HObjectAccess ForTypedArrayLength() {
- return HObjectAccess(
- kInobject,
- JSTypedArray::kLengthOffset,
- Representation::Tagged());
- }
static HObjectAccess ForAllocationSiteTransitionInfo() {
return HObjectAccess(kInobject, AllocationSite::kTransitionInfoOffset);
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Tue Sep 24 09:48:39 2013 UTC
+++ /branches/bleeding_edge/src/hydrogen.cc Wed Sep 25 08:19:35 2013 UTC
@@ -4766,7 +4766,7 @@
bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() {
if (!CanInlinePropertyAccess(*map_)) return IsStringLength();
- if (IsArrayLength()) return true;
+ if (IsJSObjectFieldAccessor()) return true;
if (!LookupDescriptor()) return false;
if (lookup_.IsFound()) return true;
return LookupInPrototypes();
@@ -4798,9 +4798,10 @@
return true;
}
- if (IsTypedArrayLength()) {
+ if (IsJSObjectFieldAccessor()) {
+ InstanceType instance_type = map_->instance_type();
for (int i = 1; i < types->length(); ++i) {
- if (types->at(i)->instance_type() != JS_TYPED_ARRAY_TYPE) return
false;
+ if (types->at(i)->instance_type() != instance_type) return false;
}
return true;
}
@@ -4821,20 +4822,10 @@
BailoutId ast_id,
BailoutId return_id,
bool can_inline_accessor) {
- if (info->IsStringLength()) {
- return New<HLoadNamedField>(
- checked_object, HObjectAccess::ForStringLength());
- }
- if (info->IsArrayLength()) {
- return New<HLoadNamedField>(
- checked_object, HObjectAccess::ForArrayLength(
- info->map()->elements_kind()));
- }
-
- if (info->IsTypedArrayLength()) {
- return New<HLoadNamedField>(
- checked_object, HObjectAccess::ForTypedArrayLength());
+ HObjectAccess access = HObjectAccess::ForMap(); // bogus default
+ if (info->GetJSObjectFieldAccess(&access)) {
+ return New<HLoadNamedField>(checked_object, access);
}
HValue* checked_holder = checked_object;
@@ -5536,16 +5527,6 @@
return new(zone()) HLoadNamedGeneric(context, object, name);
}
-
-HInstruction* HOptimizedGraphBuilder::BuildCallGetter(
- HValue* object,
- Handle<Map> map,
- Handle<JSFunction> getter,
- Handle<JSObject> holder) {
- AddCheckConstantFunction(holder, object, map);
- Add<HPushArgument>(object);
- return new(zone()) HCallConstantFunction(getter, 1);
-}
HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
=======================================
--- /branches/bleeding_edge/src/hydrogen.h Tue Sep 24 09:48:39 2013 UTC
+++ /branches/bleeding_edge/src/hydrogen.h Wed Sep 25 08:19:35 2013 UTC
@@ -30,6 +30,7 @@
#include "v8.h"
+#include "accessors.h"
#include "allocation.h"
#include "ast.h"
#include "compiler.h"
@@ -2046,19 +2047,26 @@
// PropertyAccessInfo is built for types->first().
bool CanLoadAsMonomorphic(SmallMapList* types);
- bool IsStringLength() {
- return map_->instance_type() < FIRST_NONSTRING_TYPE &&
- name_->Equals(isolate()->heap()->length_string());
- }
-
- bool IsArrayLength() {
- return map_->instance_type() == JS_ARRAY_TYPE &&
- name_->Equals(isolate()->heap()->length_string());
+ bool IsJSObjectFieldAccessor() {
+ int offset; // unused
+ return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset);
}
- bool IsTypedArrayLength() {
- return map_->instance_type() == JS_TYPED_ARRAY_TYPE &&
- name_->Equals(isolate()->heap()->length_string());
+ bool GetJSObjectFieldAccess(HObjectAccess* access) {
+ if (IsStringLength()) {
+ *access = HObjectAccess::ForStringLength();
+ return true;
+ } else if (IsArrayLength()) {
+ *access = HObjectAccess::ForArrayLength(map_->elements_kind());
+ return true;
+ } else {
+ int offset;
+ if (Accessors::IsJSObjectFieldAccessor(map_, name_, &offset)) {
+ *access = HObjectAccess::ForJSObjectOffset(offset);
+ return true;
+ }
+ return false;
+ }
}
bool has_holder() { return !holder_.is_null(); }
@@ -2072,6 +2080,16 @@
private:
Isolate* isolate() { return lookup_.isolate(); }
+
+ bool IsStringLength() {
+ return map_->instance_type() < FIRST_NONSTRING_TYPE &&
+ name_->Equals(isolate()->heap()->length_string());
+ }
+
+ bool IsArrayLength() {
+ return map_->instance_type() == JS_ARRAY_TYPE &&
+ name_->Equals(isolate()->heap()->length_string());
+ }
bool LoadResult(Handle<Map> map);
bool LookupDescriptor();
@@ -2173,10 +2191,6 @@
HInstruction* BuildLoadNamedGeneric(HValue* object,
Handle<String> name,
Property* expr);
- HInstruction* BuildCallGetter(HValue* object,
- Handle<Map> map,
- Handle<JSFunction> getter,
- Handle<JSObject> holder);
HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map);
=======================================
--- /branches/bleeding_edge/src/ic.cc Thu Sep 19 18:19:24 2013 UTC
+++ /branches/bleeding_edge/src/ic.cc Wed Sep 25 08:19:35 2013 UTC
@@ -1348,20 +1348,19 @@
if (!holder.is_identical_to(receiver)) break;
return isolate()->stub_cache()->ComputeLoadNormal(name, receiver);
case CALLBACKS: {
- Handle<Object> callback(lookup->GetCallbackObject(), isolate());
- if (name->Equals(isolate()->heap()->length_string())) {
- if (receiver->IsJSArray()) {
- PropertyIndex lengthIndex = PropertyIndex::NewHeaderIndex(
- JSArray::kLengthOffset / kPointerSize);
- return isolate()->stub_cache()->ComputeLoadField(
- name, receiver, receiver, lengthIndex,
Representation::Tagged());
- } else if (receiver->IsJSTypedArray()) {
- PropertyIndex lengthIndex = PropertyIndex::NewHeaderIndex(
- JSTypedArray::kLengthOffset / kPointerSize);
+ {
+ // Use simple field loads for some well-known callback properties.
+ int object_offset;
+ Handle<Map> map(receiver->map());
+ if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset))
{
+ PropertyIndex index =
+ PropertyIndex::NewHeaderIndex(object_offset / kPointerSize);
return isolate()->stub_cache()->ComputeLoadField(
- name, receiver, receiver, lengthIndex,
Representation::Tagged());
+ name, receiver, receiver, index, Representation::Tagged());
}
}
+
+ Handle<Object> callback(lookup->GetCallbackObject(), isolate());
if (callback->IsExecutableAccessorInfo()) {
Handle<ExecutableAccessorInfo> info =
Handle<ExecutableAccessorInfo>::cast(callback);
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.