Implement compress CompressibleStrings on GC reclaim end event

* Compress CompressibleStrings on GC reclaim end event
  - if there is reference about data of CompressibleString on stack, we should give up compressing.
    we don't need to search heap space because I redesigned StringView
    (we should not store string buffer data on heap without owner)
* Redesign StringView
  - Don't save string buffer address as its member. because buffer of CompressibleString can be deleted
  - If we don't save string buffer address on StringView, parser performance may dropped.
    becuase parser access string data a lot.
    so I introduce ParserStringView. it saves buffer address. we should ParserStringView on parser only.
    we can save string buffer address while parsing. because GC is disabled while parsing.

* Enable CompressibleString always
* Implement cache of RegExpOptionStrings
* Implement finding system locale function on RuntimeICUBinder avoiding call uloc_getDefault.

Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
Seonghyun Kim 2019-12-26 10:20:10 +09:00 committed by Hyukwoo Park
commit caa0fbc3fe
32 changed files with 1020 additions and 394 deletions

View file

@ -95,6 +95,7 @@ ObjectRareData::ObjectRareData(Object* obj)
m_isSpreadArrayObject = false;
m_shouldUpdateEnumerateObject = false;
m_hasNonWritableLastIndexRegexpObject = false;
m_arrayObjectFastModeBufferExpandCount = 0;
m_extraData = nullptr;
m_internalSlot = nullptr;
}
@ -1628,29 +1629,43 @@ Value Object::speciesConstructor(ExecutionState& state, const Value& defaultCons
String* Object::optionString(ExecutionState& state)
{
char flags[6] = { 0 };
int flags_idx = 0;
size_t flagsIdx = 0;
size_t cacheIndex = 0;
if (this->get(state, ObjectPropertyName(state, state.context()->staticStrings().global)).value(state, this).toBoolean(state)) {
flags[flags_idx++] = 'g';
flags[flagsIdx++] = 'g';
cacheIndex |= 1 << 0;
}
if (this->get(state, ObjectPropertyName(state, state.context()->staticStrings().ignoreCase)).value(state, this).toBoolean(state)) {
flags[flags_idx++] = 'i';
flags[flagsIdx++] = 'i';
cacheIndex |= 1 << 1;
}
if (this->get(state, ObjectPropertyName(state, state.context()->staticStrings().multiline)).value(state, this).toBoolean(state)) {
flags[flags_idx++] = 'm';
flags[flagsIdx++] = 'm';
cacheIndex |= 1 << 2;
}
if (this->get(state, ObjectPropertyName(state, state.context()->staticStrings().unicode)).value(state, this).toBoolean(state)) {
flags[flags_idx++] = 'u';
flags[flagsIdx++] = 'u';
cacheIndex |= 1 << 3;
}
if (this->get(state, ObjectPropertyName(state, state.context()->staticStrings().sticky)).value(state, this).toBoolean(state)) {
flags[flags_idx++] = 'y';
flags[flagsIdx++] = 'y';
cacheIndex |= 1 << 4;
}
return new ASCIIString(flags);
ASCIIString* result;
auto cache = state.context()->vmInstance()->regexpOptionStringCache();
if (cache[cacheIndex]) {
result = cache[cacheIndex];
} else {
result = cache[cacheIndex] = new ASCIIString(flags, flagsIdx);
}
return result;
}
bool Object::isRegExp(ExecutionState& state)