void JSGlobalObject::haveABadTime(VM& vm) { ASSERT(&vm == &this->vm()); if (isHavingABadTime()) return; // Make sure that all allocations or indexed storage transitions that are inlining // the assumption that it's safe to transition to a non-SlowPut array storage don't // do so anymore. m_havingABadTimeWatchpoint->notifyWrite(); ASSERT(isHavingABadTime()); // The watchpoint is what tells us that we're having a bad time. // Make sure that all JSArray allocations that load the appropriate structure from // this object now load a structure that uses SlowPut. for (unsigned i = 0; i < NumberOfIndexingShapes; ++i) m_arrayStructureForIndexingShapeDuringAllocation[i].set(vm, this, originalArrayStructureForIndexingType(ArrayWithSlowPutArrayStorage)); // Make sure that all objects that have indexed storage switch to the slow kind of // indexed storage. MarkedArgumentBuffer foundObjects; // Use MarkedArgumentBuffer because switchToSlowPutArrayStorage() may GC. ObjectsWithBrokenIndexingFinder finder(foundObjects, this); vm.heap.objectSpace().forEachLiveCell(finder); while (!foundObjects.isEmpty()) { JSObject* object = asObject(foundObjects.last()); foundObjects.removeLast(); ASSERT(hasBrokenIndexing(object)); object->switchToSlowPutArrayStorage(vm); } }
JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); UString u = s; RefPtr<RegExp> reg; RegExpObject* imp = 0; if (a0.isObject(&RegExpObject::info)) reg = asRegExpObject(a0)->regExp(); else { /* * ECMA 15.5.4.12 String.prototype.search (regexp) * If regexp is not an object whose [[Class]] property is "RegExp", it is * replaced with the result of the expression new RegExp(regexp). */ reg = RegExp::create(&exec->globalData(), a0.toString(exec)); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; int matchLength; regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength); if (!(reg->global())) { // case without 'g' flag is handled like RegExp.prototype.exec if (pos < 0) return jsNull(); return regExpConstructor->arrayOfMatches(exec); } // return array of matches MarkedArgumentBuffer list; int lastIndex = 0; while (pos >= 0) { list.append(jsSubstring(exec, u, pos, matchLength)); lastIndex = pos; pos += matchLength == 0 ? 1 : matchLength; regExpConstructor->performMatch(reg.get(), u, pos, pos, matchLength); } if (imp) imp->setLastIndex(lastIndex); if (list.isEmpty()) { // if there are no matches at all, it's important to return // Null instead of an empty array, because this matches // other browsers and because Null is a false value. return jsNull(); } return constructArray(exec, list); }
JSValue RegExpObject::matchGlobal(ExecState* exec, JSGlobalObject* globalObject, JSString* string) { RegExp* regExp = this->regExp(); ASSERT(regExp->global()); VM* vm = &globalObject->vm(); setLastIndex(exec, 0); if (exec->hadException()) return jsUndefined(); String s = string->value(exec); RegExpConstructor* regExpConstructor = globalObject->regExpConstructor(); MatchResult result = regExpConstructor->performMatch(*vm, regExp, string, s, 0); // return array of matches MarkedArgumentBuffer list; // We defend ourselves from crazy. const size_t maximumReasonableMatchSize = 1000000000; if (regExp->unicode()) { unsigned stringLength = s.length(); while (result) { if (list.size() > maximumReasonableMatchSize) { throwOutOfMemoryError(exec); return jsUndefined(); } size_t end = result.end; size_t length = end - result.start; list.append(jsSubstring(exec, s, result.start, length)); if (!length) end = advanceStringUnicode(s, stringLength, end); result = regExpConstructor->performMatch(*vm, regExp, string, s, end); } } else { while (result) { if (list.size() > maximumReasonableMatchSize) { throwOutOfMemoryError(exec); return jsUndefined(); } size_t end = result.end; size_t length = end - result.start; list.append(jsSubstring(exec, s, result.start, length)); if (!length) ++end; result = regExpConstructor->performMatch(*vm, regExp, string, s, end); } } if (list.isEmpty()) { // if there are no matches at all, it's important to return // Null instead of an empty array, because this matches // other browsers and because Null is a false value. return jsNull(); } return constructArray(exec, static_cast<ArrayAllocationProfile*>(0), list); }