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&);
}