Title: [185597] trunk/Source/_javascript_Core
Revision
185597
Author
akl...@apple.com
Date
2015-06-16 11:38:04 -0700 (Tue, 16 Jun 2015)

Log Message

[JSC] Pre-bake final Structure for RegExp matches arrays.
<https://webkit.org/b/146006>

Reviewed by Darin Adler.

Since we always add the "index" and "input" fields to RegExp matches arrays,
cache a finished structure on the global object so we can create these arrays without
starting from scratch with a bare array every time.

10% progression on Octane/regexp (on my MBP.)

* runtime/JSArray.h:
(JSC::JSArray::create):
(JSC::JSArray::tryCreateUninitialized):
(JSC::JSArray::createWithButterfly): Factored out JSArray construction into a helper
so we can call this from RegExpMatchesArray.cpp.

* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::regExpMatchesArrayStructure): Add a cached Structure for RegExp
subpattern matches arrays.

* runtime/JSObject.h:
(JSC::JSNonFinalObject::finishCreation): Tweak assertion that used to check that
JSNonFinalObjects always start out with zero capacity. Since RegExp matches arrays now
start out with capacity for 2 properties, that won't work. Change it to check that we
don't have inline storage instead, since that should only be used by final objects.

* runtime/RegExpMatchesArray.h:
* runtime/RegExpMatchesArray.cpp:
(JSC::tryCreateUninitializedRegExpMatchesArray): Helper to construct a JSArray with
the cached Structure and a Butterfly with 2 slots of property storage.

(JSC::createRegExpMatchesArray):
(JSC::createRegExpMatchesArrayStructure): Creates the array Structure that gets cached
by the JSGlobalObject.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (185596 => 185597)


--- trunk/Source/_javascript_Core/ChangeLog	2015-06-16 18:34:24 UTC (rev 185596)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-06-16 18:38:04 UTC (rev 185597)
@@ -1,3 +1,44 @@
+2015-06-16  Andreas Kling  <akl...@apple.com>
+
+        [JSC] Pre-bake final Structure for RegExp matches arrays.
+        <https://webkit.org/b/146006>
+
+        Reviewed by Darin Adler.
+
+        Since we always add the "index" and "input" fields to RegExp matches arrays,
+        cache a finished structure on the global object so we can create these arrays without
+        starting from scratch with a bare array every time.
+
+        10% progression on Octane/regexp (on my MBP.)
+
+        * runtime/JSArray.h:
+        (JSC::JSArray::create):
+        (JSC::JSArray::tryCreateUninitialized):
+        (JSC::JSArray::createWithButterfly): Factored out JSArray construction into a helper
+        so we can call this from RegExpMatchesArray.cpp.
+
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::visitChildren):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::regExpMatchesArrayStructure): Add a cached Structure for RegExp
+        subpattern matches arrays.
+
+        * runtime/JSObject.h:
+        (JSC::JSNonFinalObject::finishCreation): Tweak assertion that used to check that
+        JSNonFinalObjects always start out with zero capacity. Since RegExp matches arrays now
+        start out with capacity for 2 properties, that won't work. Change it to check that we
+        don't have inline storage instead, since that should only be used by final objects.
+
+        * runtime/RegExpMatchesArray.h:
+        * runtime/RegExpMatchesArray.cpp:
+        (JSC::tryCreateUninitializedRegExpMatchesArray): Helper to construct a JSArray with
+        the cached Structure and a Butterfly with 2 slots of property storage.
+
+        (JSC::createRegExpMatchesArray):
+        (JSC::createRegExpMatchesArrayStructure): Creates the array Structure that gets cached
+        by the JSGlobalObject.
+
 2015-06-16  Saam Barati  <saambara...@gmail.com>
 
         LLInt's code path for get_from_scope with case GlobalVarWithVarInjectionChecks has dead code

Modified: trunk/Source/_javascript_Core/runtime/JSArray.h (185596 => 185597)


--- trunk/Source/_javascript_Core/runtime/JSArray.h	2015-06-16 18:34:24 UTC (rev 185596)
+++ trunk/Source/_javascript_Core/runtime/JSArray.h	2015-06-16 18:38:04 UTC (rev 185597)
@@ -53,6 +53,7 @@
 
 public:
     static JSArray* create(VM&, Structure*, unsigned initialLength = 0);
+    static JSArray* createWithButterfly(VM&, Structure*, Butterfly*);
 
     // tryCreateUninitialized is used for fast construction of arrays whose size and
     // contents are known at time of creation. Clients of this interface must:
@@ -213,9 +214,8 @@
             || structure->indexingType() == ArrayWithArrayStorage);
         butterfly = createArrayButterfly(vm, 0, initialLength);
     }
-    JSArray* array = new (NotNull, allocateCell<JSArray>(vm.heap)) JSArray(vm, structure, butterfly);
-    array->finishCreation(vm);
-    return array;
+
+    return createWithButterfly(vm, structure, butterfly);
 }
 
 inline JSArray* JSArray::tryCreateUninitialized(VM& vm, Structure* structure, unsigned initialLength)
@@ -253,7 +253,12 @@
         storage->m_sparseMap.clear();
         storage->m_numValuesInVector = initialLength;
     }
-        
+
+    return createWithButterfly(vm, structure, butterfly);
+}
+
+inline JSArray* JSArray::createWithButterfly(VM& vm, Structure* structure, Butterfly* butterfly)
+{
     JSArray* array = new (NotNull, allocateCell<JSArray>(vm.heap)) JSArray(vm, structure, butterfly);
     array->finishCreation(vm);
     return array;

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (185596 => 185597)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2015-06-16 18:34:24 UTC (rev 185596)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2015-06-16 18:38:04 UTC (rev 185597)
@@ -316,6 +316,7 @@
     
     m_regExpPrototype.set(vm, this, RegExpPrototype::create(vm, RegExpPrototype::createStructure(vm, this, m_objectPrototype.get()), emptyRegex));
     m_regExpStructure.set(vm, this, RegExpObject::createStructure(vm, this, m_regExpPrototype.get()));
+    m_regExpMatchesArrayStructure.set(vm, this, createRegExpMatchesArrayStructure(vm, *this));
     
 #if ENABLE(PROMISES)
     m_promisePrototype.set(vm, this, JSPromisePrototype::create(exec, this, JSPromisePrototype::createStructure(vm, this, m_objectPrototype.get())));
@@ -778,6 +779,7 @@
     visitor.append(&thisObject->m_namedFunctionStructure);
     visitor.append(&thisObject->m_symbolObjectStructure);
     visitor.append(&thisObject->m_regExpStructure);
+    visitor.append(&thisObject->m_regExpMatchesArrayStructure);
     visitor.append(&thisObject->m_consoleStructure);
     visitor.append(&thisObject->m_dollarVMStructure);
     visitor.append(&thisObject->m_internalFunctionStructure);

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (185596 => 185597)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2015-06-16 18:34:24 UTC (rev 185596)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2015-06-16 18:38:04 UTC (rev 185597)
@@ -248,6 +248,8 @@
     
     WriteBarrier<Structure> m_iteratorResultStructure;
 
+    WriteBarrier<Structure> m_regExpMatchesArrayStructure;
+
 #if ENABLE(PROMISES)
     WriteBarrier<Structure> m_promiseStructure;
 #endif // ENABLE(PROMISES)
@@ -488,6 +490,7 @@
     Structure* symbolObjectStructure() const { return m_symbolObjectStructure.get(); }
     Structure* iteratorResultStructure() const { return m_iteratorResultStructure.get(); }
     static ptrdiff_t iteratorResultStructureOffset() { return OBJECT_OFFSETOF(JSGlobalObject, m_iteratorResultStructure); }
+    Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); }
 
 #if ENABLE(PROMISES)
     Structure* promiseStructure() const { return m_promiseStructure.get(); }

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (185596 => 185597)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2015-06-16 18:34:24 UTC (rev 185596)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2015-06-16 18:38:04 UTC (rev 185597)
@@ -1011,7 +1011,7 @@
     void finishCreation(VM& vm)
     {
         Base::finishCreation(vm);
-        ASSERT(!this->structure()->totalStorageCapacity());
+        ASSERT(!this->structure()->hasInlineStorage());
         ASSERT(classInfo());
     }
 };

Modified: trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.cpp (185596 => 185597)


--- trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.cpp	2015-06-16 18:34:24 UTC (rev 185596)
+++ trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.cpp	2015-06-16 18:38:04 UTC (rev 185597)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,11 +31,30 @@
 
 namespace JSC {
 
+static const PropertyOffset indexPropertyOffset = 100;
+static const PropertyOffset inputPropertyOffset = 101;
+
+static JSArray* tryCreateUninitializedRegExpMatchesArray(VM& vm, Structure* structure, unsigned initialLength)
+{
+    unsigned vectorLength = std::max(BASE_VECTOR_LEN, initialLength);
+    if (vectorLength > MAX_STORAGE_VECTOR_LENGTH)
+        return 0;
+
+    void* temp;
+    if (!vm.heap.tryAllocateStorage(0, Butterfly::totalSize(0, structure->outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)), &temp))
+        return 0;
+    Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure->outOfLineCapacity());
+    butterfly->setVectorLength(vectorLength);
+    butterfly->setPublicLength(initialLength);
+
+    return JSArray::createWithButterfly(vm, structure, butterfly);
+}
+
 JSArray* createRegExpMatchesArray(ExecState* exec, JSString* input, RegExp* regExp, MatchResult result)
 {
     ASSERT(result);
     VM& vm = exec->vm();
-    JSArray* array = JSArray::tryCreateUninitialized(vm, exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), regExp->numSubpatterns() + 1);
+    JSArray* array = tryCreateUninitializedRegExpMatchesArray(vm, exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1);
     RELEASE_ASSERT(array);
 
     SamplingRegion samplingRegion("Reifying substring properties");
@@ -58,10 +77,21 @@
         }
     }
 
-    array->putDirect(vm, vm.propertyNames->index, jsNumber(result.start));
-    array->putDirect(vm, vm.propertyNames->input, input);
+    array->putDirect(vm, indexPropertyOffset, jsNumber(result.start));
+    array->putDirect(vm, inputPropertyOffset, input);
 
     return array;
 }
 
+Structure* createRegExpMatchesArrayStructure(VM& vm, JSGlobalObject& globalObject)
+{
+    Structure* structure = globalObject.arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
+    PropertyOffset offset;
+    structure = structure->addPropertyTransition(vm, structure, vm.propertyNames->index, 0, offset);
+    ASSERT(offset == indexPropertyOffset);
+    structure = structure->addPropertyTransition(vm, structure, vm.propertyNames->input, 0, offset);
+    ASSERT(offset == inputPropertyOffset);
+    return structure;
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.h (185596 => 185597)


--- trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.h	2015-06-16 18:34:24 UTC (rev 185596)
+++ trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.h	2015-06-16 18:38:04 UTC (rev 185597)
@@ -27,6 +27,7 @@
 namespace JSC {
 
 JSArray* createRegExpMatchesArray(ExecState*, JSString*, RegExp*, MatchResult);
+Structure* createRegExpMatchesArrayStructure(VM&, JSGlobalObject&);
 
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to