summaryrefslogtreecommitdiff
path: root/deps/v8/src/runtime.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/runtime.cc')
-rw-r--r--deps/v8/src/runtime.cc427
1 files changed, 167 insertions, 260 deletions
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc
index fc6ca762f..43a673423 100644
--- a/deps/v8/src/runtime.cc
+++ b/deps/v8/src/runtime.cc
@@ -98,7 +98,7 @@ namespace internal {
static StaticResource<StringInputBuffer> runtime_string_input_buffer;
-static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
+MUST_USE_RESULT static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
StackLimitCheck check;
if (check.HasOverflowed()) return Top::StackOverflow();
@@ -160,13 +160,22 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
switch (copy->GetElementsKind()) {
case JSObject::FAST_ELEMENTS: {
FixedArray* elements = FixedArray::cast(copy->elements());
- for (int i = 0; i < elements->length(); i++) {
- Object* value = elements->get(i);
- if (value->IsJSObject()) {
- JSObject* js_object = JSObject::cast(value);
- result = DeepCopyBoilerplate(js_object);
- if (result->IsFailure()) return result;
- elements->set(i, result);
+ if (elements->map() == Heap::fixed_cow_array_map()) {
+ Counters::cow_arrays_created_runtime.Increment();
+#ifdef DEBUG
+ for (int i = 0; i < elements->length(); i++) {
+ ASSERT(!elements->get(i)->IsJSObject());
+ }
+#endif
+ } else {
+ for (int i = 0; i < elements->length(); i++) {
+ Object* value = elements->get(i);
+ if (value->IsJSObject()) {
+ JSObject* js_object = JSObject::cast(value);
+ result = DeepCopyBoilerplate(js_object);
+ if (result->IsFailure()) return result;
+ elements->set(i, result);
+ }
}
}
break;
@@ -343,18 +352,29 @@ static Handle<Object> CreateArrayLiteralBoilerplate(
JSFunction::GlobalContextFromLiterals(*literals)->array_function());
Handle<Object> object = Factory::NewJSObject(constructor);
- Handle<Object> copied_elements = Factory::CopyFixedArray(elements);
+ const bool is_cow = (elements->map() == Heap::fixed_cow_array_map());
+ Handle<FixedArray> copied_elements =
+ is_cow ? elements : Factory::CopyFixedArray(elements);
Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements);
- for (int i = 0; i < content->length(); i++) {
- if (content->get(i)->IsFixedArray()) {
- // The value contains the constant_properties of a
- // simple object literal.
- Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
- Handle<Object> result =
- CreateLiteralBoilerplate(literals, fa);
- if (result.is_null()) return result;
- content->set(i, *result);
+ if (is_cow) {
+#ifdef DEBUG
+ // Copy-on-write arrays must be shallow (and simple).
+ for (int i = 0; i < content->length(); i++) {
+ ASSERT(!content->get(i)->IsFixedArray());
+ }
+#endif
+ } else {
+ for (int i = 0; i < content->length(); i++) {
+ if (content->get(i)->IsFixedArray()) {
+ // The value contains the constant_properties of a
+ // simple object literal.
+ Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
+ Handle<Object> result =
+ CreateLiteralBoilerplate(literals, fa);
+ if (result.is_null()) return result;
+ content->set(i, *result);
+ }
}
}
@@ -483,6 +503,10 @@ static Object* Runtime_CreateArrayLiteralShallow(Arguments args) {
// Update the functions literal and return the boilerplate.
literals->set(literals_index, *boilerplate);
}
+ if (JSObject::cast(*boilerplate)->elements()->map() ==
+ Heap::fixed_cow_array_map()) {
+ Counters::cow_arrays_created_runtime.Increment();
+ }
return Heap::CopyJSObject(JSObject::cast(*boilerplate));
}
@@ -956,7 +980,9 @@ static Object* Runtime_DeclareContextSlot(Arguments args) {
context->set(index, *initial_value);
}
} else {
- Handle<JSObject>::cast(holder)->SetElement(index, *initial_value);
+ // The holder is an arguments object.
+ Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
+ SetElement(arguments, index, initial_value);
}
} else {
// Slow case: The property is not in the FixedArray part of the context.
@@ -1214,7 +1240,8 @@ static Object* Runtime_InitializeConstContextSlot(Arguments args) {
} else {
// The holder is an arguments object.
ASSERT((attributes & READ_ONLY) == 0);
- Handle<JSObject>::cast(holder)->SetElement(index, *value);
+ Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
+ SetElement(arguments, index, value);
}
return *value;
}
@@ -1340,6 +1367,63 @@ static Object* Runtime_RegExpConstructResult(Arguments args) {
}
+static Object* Runtime_RegExpCloneResult(Arguments args) {
+ ASSERT(args.length() == 1);
+ Map* regexp_result_map;
+ {
+ AssertNoAllocation no_gc;
+ HandleScope handles;
+ regexp_result_map = Top::global_context()->regexp_result_map();
+ }
+ if (!args[0]->IsJSArray()) return args[0];
+
+ JSArray* result = JSArray::cast(args[0]);
+ // Arguments to RegExpCloneResult should always be fresh RegExp exec call
+ // results (either a fresh JSRegExpResult or null).
+ // If the argument is not a JSRegExpResult, or isn't unmodified, just return
+ // the argument uncloned.
+ if (result->map() != regexp_result_map) return result;
+
+ // Having the original JSRegExpResult map guarantees that we have
+ // fast elements and no properties except the two in-object properties.
+ ASSERT(result->HasFastElements());
+ ASSERT(result->properties() == Heap::empty_fixed_array());
+ ASSERT_EQ(2, regexp_result_map->inobject_properties());
+
+ Object* new_array_alloc = Heap::AllocateRaw(JSRegExpResult::kSize,
+ NEW_SPACE,
+ OLD_POINTER_SPACE);
+ if (new_array_alloc->IsFailure()) return new_array_alloc;
+
+ // Set HeapObject map to JSRegExpResult map.
+ reinterpret_cast<HeapObject*>(new_array_alloc)->set_map(regexp_result_map);
+
+ JSArray* new_array = JSArray::cast(new_array_alloc);
+
+ // Copy JSObject properties.
+ new_array->set_properties(result->properties()); // Empty FixedArray.
+
+ // Copy JSObject elements as copy-on-write.
+ FixedArray* elements = FixedArray::cast(result->elements());
+ if (elements != Heap::empty_fixed_array()) {
+ elements->set_map(Heap::fixed_cow_array_map());
+ }
+ new_array->set_elements(elements);
+
+ // Copy JSArray length.
+ new_array->set_length(result->length());
+
+ // Copy JSRegExpResult in-object property fields input and index.
+ new_array->FastPropertyAtPut(JSRegExpResult::kIndexIndex,
+ result->FastPropertyAt(
+ JSRegExpResult::kIndexIndex));
+ new_array->FastPropertyAtPut(JSRegExpResult::kInputIndex,
+ result->FastPropertyAt(
+ JSRegExpResult::kInputIndex));
+ return new_array;
+}
+
+
static Object* Runtime_RegExpInitializeObject(Arguments args) {
AssertNoAllocation no_alloc;
ASSERT(args.length() == 5);
@@ -1620,7 +1704,6 @@ static Object* Runtime_SetCode(Arguments args) {
RUNTIME_ASSERT(code->IsJSFunction());
Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
Handle<SharedFunctionInfo> shared(fun->shared());
- SetExpectedNofProperties(target, shared->expected_nof_properties());
if (!EnsureCompiled(shared, KEEP_EXCEPTION)) {
return Failure::Exception();
@@ -1665,6 +1748,17 @@ static Object* Runtime_SetCode(Arguments args) {
}
+static Object* Runtime_SetExpectedNumberOfProperties(Arguments args) {
+ HandleScope scope;
+ ASSERT(args.length() == 2);
+ CONVERT_ARG_CHECKED(JSFunction, function, 0);
+ CONVERT_SMI_CHECKED(num, args[1]);
+ RUNTIME_ASSERT(num >= 0);
+ SetExpectedNofProperties(function, num);
+ return Heap::undefined_value();
+}
+
+
static Object* CharFromCode(Object* char_code) {
uint32_t code;
if (char_code->ToArrayIndex(&code)) {
@@ -2724,40 +2818,6 @@ static int BoyerMooreIndexOf(Vector<const schar> subject,
}
-template <typename schar>
-static inline int SingleCharIndexOf(Vector<const schar> string,
- schar pattern_char,
- int start_index) {
- if (sizeof(schar) == 1) {
- const schar* pos = reinterpret_cast<const schar*>(
- memchr(string.start() + start_index,
- pattern_char,
- string.length() - start_index));
- if (pos == NULL) return -1;
- return static_cast<int>(pos - string.start());
- }
- for (int i = start_index, n = string.length(); i < n; i++) {
- if (pattern_char == string[i]) {
- return i;
- }
- }
- return -1;
-}
-
-
-template <typename schar>
-static int SingleCharLastIndexOf(Vector<const schar> string,
- schar pattern_char,
- int start_index) {
- for (int i = start_index; i >= 0; i--) {
- if (pattern_char == string[i]) {
- return i;
- }
- }
- return -1;
-}
-
-
// Trivial string search for shorter strings.
// On return, if "complete" is set to true, the return value is the
// final result of searching for the patter in the subject.
@@ -2769,6 +2829,7 @@ static int SimpleIndexOf(Vector<const schar> subject,
Vector<const pchar> pattern,
int idx,
bool* complete) {
+ ASSERT(pattern.length() > 1);
// Badness is a count of how much work we have done. When we have
// done enough work we decide it's probably worth switching to a better
// algorithm.
@@ -2831,12 +2892,12 @@ static int SimpleIndexOf(Vector<const schar> subject,
if (subject[i] != pattern_first_char) continue;
}
int j = 1;
- do {
+ while (j < pattern.length()) {
if (pattern[j] != subject[i+j]) {
break;
}
j++;
- } while (j < pattern.length());
+ }
if (j == pattern.length()) {
return i;
}
@@ -2852,7 +2913,6 @@ enum StringSearchStrategy { SEARCH_FAIL, SEARCH_SHORT, SEARCH_LONG };
template <typename pchar>
static inline StringSearchStrategy InitializeStringSearch(
Vector<const pchar> pat, bool ascii_subject) {
- ASSERT(pat.length() > 1);
// We have an ASCII haystack and a non-ASCII needle. Check if there
// really is a non-ASCII character in the needle and bail out if there
// is.
@@ -2938,54 +2998,15 @@ int Runtime::StringMatch(Handle<String> sub,
int subject_length = sub->length();
if (start_index + pattern_length > subject_length) return -1;
- if (!sub->IsFlat()) {
- FlattenString(sub);
- }
-
- // Searching for one specific character is common. For one
- // character patterns linear search is necessary, so any smart
- // algorithm is unnecessary overhead.
- if (pattern_length == 1) {
- AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
- String* seq_sub = *sub;
- if (seq_sub->IsConsString()) {
- seq_sub = ConsString::cast(seq_sub)->first();
- }
- if (seq_sub->IsAsciiRepresentation()) {
- uc16 pchar = pat->Get(0);
- if (pchar > String::kMaxAsciiCharCode) {
- return -1;
- }
- Vector<const char> ascii_vector =
- seq_sub->ToAsciiVector().SubVector(start_index, subject_length);
- const void* pos = memchr(ascii_vector.start(),
- static_cast<const char>(pchar),
- static_cast<size_t>(ascii_vector.length()));
- if (pos == NULL) {
- return -1;
- }
- return static_cast<int>(reinterpret_cast<const char*>(pos)
- - ascii_vector.start() + start_index);
- }
- return SingleCharIndexOf(seq_sub->ToUC16Vector(),
- pat->Get(0),
- start_index);
- }
-
- if (!pat->IsFlat()) {
- FlattenString(pat);
- }
+ if (!sub->IsFlat()) FlattenString(sub);
+ if (!pat->IsFlat()) FlattenString(pat);
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
// Extract flattened substrings of cons strings before determining asciiness.
String* seq_sub = *sub;
- if (seq_sub->IsConsString()) {
- seq_sub = ConsString::cast(seq_sub)->first();
- }
+ if (seq_sub->IsConsString()) seq_sub = ConsString::cast(seq_sub)->first();
String* seq_pat = *pat;
- if (seq_pat->IsConsString()) {
- seq_pat = ConsString::cast(seq_pat)->first();
- }
+ if (seq_pat->IsConsString()) seq_pat = ConsString::cast(seq_pat)->first();
// dispatch on type of strings
if (seq_pat->IsAsciiRepresentation()) {
@@ -3075,30 +3096,8 @@ static Object* Runtime_StringLastIndexOf(Arguments args) {
return Smi::FromInt(start_index);
}
- if (!sub->IsFlat()) {
- FlattenString(sub);
- }
-
- if (pat_length == 1) {
- AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
- if (sub->IsAsciiRepresentation()) {
- uc16 pchar = pat->Get(0);
- if (pchar > String::kMaxAsciiCharCode) {
- return Smi::FromInt(-1);
- }
- return Smi::FromInt(SingleCharLastIndexOf(sub->ToAsciiVector(),
- static_cast<char>(pat->Get(0)),
- start_index));
- } else {
- return Smi::FromInt(SingleCharLastIndexOf(sub->ToUC16Vector(),
- pat->Get(0),
- start_index));
- }
- }
-
- if (!pat->IsFlat()) {
- FlattenString(pat);
- }
+ if (!sub->IsFlat()) FlattenString(sub);
+ if (!pat->IsFlat()) FlattenString(pat);
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
@@ -3276,88 +3275,6 @@ static void SetLastMatchInfoNoCaptures(Handle<String> subject,
}
-template <typename schar>
-static bool SearchCharMultiple(Vector<schar> subject,
- String* pattern,
- schar pattern_char,
- FixedArrayBuilder* builder,
- int* match_pos) {
- // Position of last match.
- int pos = *match_pos;
- int subject_length = subject.length();
- while (pos < subject_length) {
- int match_end = pos + 1;
- if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
- *match_pos = pos;
- return false;
- }
- int new_pos = SingleCharIndexOf(subject, pattern_char, match_end);
- if (new_pos >= 0) {
- // Match has been found.
- if (new_pos > match_end) {
- ReplacementStringBuilder::AddSubjectSlice(builder, match_end, new_pos);
- }
- pos = new_pos;
- builder->Add(pattern);
- } else {
- break;
- }
- }
- if (pos + 1 < subject_length) {
- ReplacementStringBuilder::AddSubjectSlice(builder, pos + 1, subject_length);
- }
- *match_pos = pos;
- return true;
-}
-
-
-static bool SearchCharMultiple(Handle<String> subject,
- Handle<String> pattern,
- Handle<JSArray> last_match_info,
- FixedArrayBuilder* builder) {
- ASSERT(subject->IsFlat());
- ASSERT_EQ(1, pattern->length());
- uc16 pattern_char = pattern->Get(0);
- // Treating position before first as initial "previous match position".
- int match_pos = -1;
-
- for (;;) { // Break when search complete.
- builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
- AssertNoAllocation no_gc;
- if (subject->IsAsciiRepresentation()) {
- if (pattern_char > String::kMaxAsciiCharCode) {
- break;
- }
- Vector<const char> subject_vector = subject->ToAsciiVector();
- char pattern_ascii_char = static_cast<char>(pattern_char);
- bool complete = SearchCharMultiple<const char>(subject_vector,
- *pattern,
- pattern_ascii_char,
- builder,
- &match_pos);
- if (complete) break;
- } else {
- Vector<const uc16> subject_vector = subject->ToUC16Vector();
- bool complete = SearchCharMultiple<const uc16>(subject_vector,
- *pattern,
- pattern_char,
- builder,
- &match_pos);
- if (complete) break;
- }
- }
-
- if (match_pos >= 0) {
- SetLastMatchInfoNoCaptures(subject,
- last_match_info,
- match_pos,
- match_pos + 1);
- return true;
- }
- return false; // No matches at all.
-}
-
-
template <typename schar, typename pchar>
static bool SearchStringMultiple(Vector<schar> subject,
String* pattern,
@@ -3435,7 +3352,6 @@ static bool SearchStringMultiple(Handle<String> subject,
FixedArrayBuilder* builder) {
ASSERT(subject->IsFlat());
ASSERT(pattern->IsFlat());
- ASSERT(pattern->length() > 1);
// Treating as if a previous match was before first character.
int match_pos = -pattern->length();
@@ -3500,7 +3416,7 @@ static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple(
if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
OffsetsVector registers(required_registers);
- Vector<int> register_vector(registers.vector(), registers.length());
+ Vector<int32_t> register_vector(registers.vector(), registers.length());
int subject_length = subject->length();
for (;;) { // Break on failure, return on exception.
@@ -3562,7 +3478,7 @@ static RegExpImpl::IrregexpResult SearchRegExpMultiple(
if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
OffsetsVector registers(required_registers);
- Vector<int> register_vector(registers.vector(), registers.length());
+ Vector<int32_t> register_vector(registers.vector(), registers.length());
RegExpImpl::IrregexpResult result =
RegExpImpl::IrregexpExecOnce(regexp,
@@ -3622,7 +3538,7 @@ static RegExpImpl::IrregexpResult SearchRegExpMultiple(
}
// Swap register vectors, so the last successful match is in
// prev_register_vector.
- Vector<int> tmp = prev_register_vector;
+ Vector<int32_t> tmp = prev_register_vector;
prev_register_vector = register_vector;
register_vector = tmp;
@@ -3693,14 +3609,6 @@ static Object* Runtime_RegExpExecMultiple(Arguments args) {
if (regexp->TypeTag() == JSRegExp::ATOM) {
Handle<String> pattern(
String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)));
- int pattern_length = pattern->length();
- if (pattern_length == 1) {
- if (SearchCharMultiple(subject, pattern, last_match_info, &builder)) {
- return *builder.ToJSArray(result_array);
- }
- return Heap::null_value();
- }
-
if (!pattern->IsFlat()) FlattenString(pattern);
if (SearchStringMultiple(subject, pattern, last_match_info, &builder)) {
return *builder.ToJSArray(result_array);
@@ -4014,7 +3922,8 @@ static Object* Runtime_DefineOrRedefineAccessorProperty(Arguments args) {
if (result.IsProperty() &&
(result.type() == FIELD || result.type() == NORMAL
|| result.type() == CONSTANT_FUNCTION)) {
- obj->DeleteProperty(name, JSObject::NORMAL_DELETION);
+ Object* ok = obj->DeleteProperty(name, JSObject::NORMAL_DELETION);
+ if (ok->IsFailure()) return ok;
}
return obj->DefineAccessor(name, flag_setter->value() == 0, fun, attr);
}
@@ -4763,6 +4672,18 @@ static Object* Runtime_StringToNumber(Arguments args) {
if (minus) {
if (d == 0) return Heap::minus_zero_value();
d = -d;
+ } else if (!subject->HasHashCode() &&
+ len <= String::kMaxArrayIndexSize &&
+ (len == 1 || data[0] != '0')) {
+ // String hash is not calculated yet but all the data are present.
+ // Update the hash field to speed up sequential convertions.
+ uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
+#ifdef DEBUG
+ subject->Hash(); // Force hash calculation.
+ ASSERT_EQ(static_cast<int>(subject->hash_field()),
+ static_cast<int>(hash));
+#endif
+ subject->set_hash_field(hash);
}
return Smi::FromInt(d);
}
@@ -5288,23 +5209,6 @@ void FindStringIndices(Vector<const schar> subject,
}
}
-template <typename schar>
-inline void FindCharIndices(Vector<const schar> subject,
- const schar pattern_char,
- ZoneList<int>* indices,
- unsigned int limit) {
- // Collect indices of pattern_char in subject, and the end-of-string index.
- // Stop after finding at most limit values.
- int index = 0;
- while (limit > 0) {
- index = SingleCharIndexOf(subject, pattern_char, index);
- if (index < 0) return;
- indices->Add(index);
- index++;
- limit--;
- }
-}
-
static Object* Runtime_StringSplit(Arguments args) {
ASSERT(args.length() == 3);
@@ -5330,22 +5234,10 @@ static Object* Runtime_StringSplit(Arguments args) {
// Find (up to limit) indices of separator and end-of-string in subject
int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
ZoneList<int> indices(initial_capacity);
- if (pattern_length == 1) {
- // Special case, go directly to fast single-character split.
- AssertNoAllocation nogc;
- uc16 pattern_char = pattern->Get(0);
- if (subject->IsTwoByteRepresentation()) {
- FindCharIndices(subject->ToUC16Vector(), pattern_char,
- &indices,
- limit);
- } else if (pattern_char <= String::kMaxAsciiCharCode) {
- FindCharIndices(subject->ToAsciiVector(),
- static_cast<char>(pattern_char),
- &indices,
- limit);
- }
- } else {
- if (!pattern->IsFlat()) FlattenString(pattern);
+ if (!pattern->IsFlat()) FlattenString(pattern);
+
+ // No allocation block.
+ {
AssertNoAllocation nogc;
if (subject->IsAsciiRepresentation()) {
Vector<const char> subject_vector = subject->ToAsciiVector();
@@ -5375,11 +5267,12 @@ static Object* Runtime_StringSplit(Arguments args) {
}
}
}
+
if (static_cast<uint32_t>(indices.length()) < limit) {
indices.Add(subject_length);
}
- // The list indices now contains the end of each part to create.
+ // The list indices now contains the end of each part to create.
// Create JSArray of substrings separated by separator.
int part_count = indices.length();
@@ -5484,6 +5377,14 @@ static Object* Runtime_StringToArray(Arguments args) {
}
+static Object* Runtime_NewStringWrapper(Arguments args) {
+ NoHandleAllocation ha;
+ ASSERT(args.length() == 1);
+ CONVERT_CHECKED(String, value, args[0]);
+ return value->ToObject();
+}
+
+
bool Runtime::IsUpperCaseChar(uint16_t ch) {
unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
int char_length = to_upper_mapping.get(ch, 0, chars);
@@ -6699,9 +6600,13 @@ static Object* Runtime_DateYMDFromTime(Arguments args) {
int year, month, day;
DateYMDFromTime(static_cast<int>(floor(t / 86400000)), year, month, day);
- res_array->SetElement(0, Smi::FromInt(year));
- res_array->SetElement(1, Smi::FromInt(month));
- res_array->SetElement(2, Smi::FromInt(day));
+ RUNTIME_ASSERT(res_array->elements()->map() == Heap::fixed_array_map());
+ FixedArray* elms = FixedArray::cast(res_array->elements());
+ RUNTIME_ASSERT(elms->length() == 3);
+
+ elms->set(0, Smi::FromInt(year));
+ elms->set(1, Smi::FromInt(month));
+ elms->set(2, Smi::FromInt(day));
return Heap::undefined_value();
}
@@ -8057,7 +7962,8 @@ static Object* Runtime_MoveArrayContents(Arguments args) {
CONVERT_CHECKED(JSArray, to, args[1]);
HeapObject* new_elements = from->elements();
Object* new_map;
- if (new_elements->map() == Heap::fixed_array_map()) {
+ if (new_elements->map() == Heap::fixed_array_map() ||
+ new_elements->map() == Heap::fixed_cow_array_map()) {
new_map = to->map()->GetFastElementsMap();
} else {
new_map = to->map()->GetSlowElementsMap();
@@ -10602,9 +10508,10 @@ Runtime::Function* Runtime::FunctionForId(FunctionId fid) {
}
-Runtime::Function* Runtime::FunctionForName(const char* name) {
+Runtime::Function* Runtime::FunctionForName(Vector<const char> name) {
for (Function* f = Runtime_functions; f->name != NULL; f++) {
- if (strcmp(f->name, name) == 0) {
+ if (strncmp(f->name, name.start(), name.length()) == 0
+ && f->name[name.length()] == 0) {
return f;
}
}