Eliminate unnecessary patching of load-length ICs in megamorphic state.

This avoid the worst case of patching ICs repeatedly with the
same stub code object.

BUG=v8:1489
Review URL: http://codereview.chromium.org/7230007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8364 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
fschneider@chromium.org 2011-06-22 10:24:40 +00:00
parent 5b7b0ce861
commit d64b48fb3c

View File

@ -860,37 +860,40 @@ MaybeObject* LoadIC::Load(State state,
}
if (FLAG_use_ic) {
Code* non_monomorphic_stub =
(state == UNINITIALIZED) ? pre_monomorphic_stub() : megamorphic_stub();
// Use specialized code for getting the length of strings and
// string wrapper objects. The length property of string wrapper
// objects is read-only and therefore always returns the length of
// the underlying string value. See ECMA-262 15.5.5.1.
if ((object->IsString() || object->IsStringWrapper()) &&
name->Equals(isolate()->heap()->length_symbol())) {
HandleScope scope(isolate());
#ifdef DEBUG
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
#endif
if (state == PREMONOMORPHIC) {
AssertNoAllocation no_allocation;
Code* stub = NULL;
if (state == UNINITIALIZED) {
stub = pre_monomorphic_stub();
} else if (state == PREMONOMORPHIC) {
if (object->IsString()) {
set_target(isolate()->builtins()->builtin(
Builtins::kLoadIC_StringLength));
stub = isolate()->builtins()->builtin(
Builtins::kLoadIC_StringLength);
} else {
set_target(isolate()->builtins()->builtin(
Builtins::kLoadIC_StringWrapperLength));
stub = isolate()->builtins()->builtin(
Builtins::kLoadIC_StringWrapperLength);
}
} else if (state == MONOMORPHIC && object->IsStringWrapper()) {
set_target(isolate()->builtins()->builtin(
Builtins::kLoadIC_StringWrapperLength));
} else {
set_target(non_monomorphic_stub);
stub = isolate()->builtins()->builtin(
Builtins::kLoadIC_StringWrapperLength);
} else if (state != MEGAMORPHIC) {
stub = megamorphic_stub();
}
if (stub != NULL) {
set_target(stub);
#ifdef DEBUG
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
#endif
}
// Get the string if we have a string wrapper object.
if (object->IsJSValue()) {
object = Handle<Object>(Handle<JSValue>::cast(object)->value(),
isolate());
return Smi::FromInt(
String::cast(Handle<JSValue>::cast(object)->value())->length());
}
return Smi::FromInt(String::cast(*object)->length());
}
@ -898,14 +901,21 @@ MaybeObject* LoadIC::Load(State state,
// Use specialized code for getting the length of arrays.
if (object->IsJSArray() &&
name->Equals(isolate()->heap()->length_symbol())) {
AssertNoAllocation no_allocation;
Code* stub = NULL;
if (state == UNINITIALIZED) {
stub = pre_monomorphic_stub();
} else if (state == PREMONOMORPHIC) {
stub = isolate()->builtins()->builtin(
Builtins::kLoadIC_ArrayLength);
} else if (state != MEGAMORPHIC) {
stub = megamorphic_stub();
}
if (stub != NULL) {
set_target(stub);
#ifdef DEBUG
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
#endif
if (state == PREMONOMORPHIC) {
set_target(isolate()->builtins()->builtin(
Builtins::kLoadIC_ArrayLength));
} else {
set_target(non_monomorphic_stub);
}
return JSArray::cast(*object)->length();
}
@ -914,14 +924,22 @@ MaybeObject* LoadIC::Load(State state,
if (object->IsJSFunction() &&
name->Equals(isolate()->heap()->prototype_symbol()) &&
JSFunction::cast(*object)->should_have_prototype()) {
{ AssertNoAllocation no_allocation;
Code* stub = NULL;
if (state == UNINITIALIZED) {
stub = pre_monomorphic_stub();
} else if (state == PREMONOMORPHIC) {
stub = isolate()->builtins()->builtin(
Builtins::kLoadIC_FunctionPrototype);
} else if (state != MEGAMORPHIC) {
stub = megamorphic_stub();
}
if (stub != NULL) {
set_target(stub);
#ifdef DEBUG
if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
#endif
if (state == PREMONOMORPHIC) {
set_target(isolate()->builtins()->builtin(
Builtins::kLoadIC_FunctionPrototype));
} else {
set_target(non_monomorphic_stub);
}
}
return Accessors::FunctionGetPrototype(*object, 0);
}