Commit 845fd15d authored by lrn@chromium.org's avatar lrn@chromium.org

Pre-create properties on JSRegExp objects

Initialize properties in single runtime call.

Review URL: http://codereview.chromium.org/1350003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4298 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 75003d7e
......@@ -723,8 +723,68 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
InstallFunction(global, "RegExp", JS_REGEXP_TYPE, JSRegExp::kSize,
Top::initial_object_prototype(), Builtins::Illegal,
true);
global_context()->set_regexp_function(*regexp_fun);
ASSERT(regexp_fun->has_initial_map());
Handle<Map> initial_map(regexp_fun->initial_map());
ASSERT_EQ(0, initial_map->inobject_properties());
Handle<DescriptorArray> descriptors = Factory::NewDescriptorArray(5);
PropertyAttributes final =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
int enum_index = 0;
{
// ECMA-262, section 15.10.7.1.
FieldDescriptor field(Heap::source_symbol(),
JSRegExp::kSourceFieldIndex,
final,
enum_index++);
descriptors->Set(0, &field);
}
{
// ECMA-262, section 15.10.7.2.
FieldDescriptor field(Heap::global_symbol(),
JSRegExp::kGlobalFieldIndex,
final,
enum_index++);
descriptors->Set(1, &field);
}
{
// ECMA-262, section 15.10.7.3.
FieldDescriptor field(Heap::ignore_case_symbol(),
JSRegExp::kIgnoreCaseFieldIndex,
final,
enum_index++);
descriptors->Set(2, &field);
}
{
// ECMA-262, section 15.10.7.4.
FieldDescriptor field(Heap::multiline_symbol(),
JSRegExp::kMultilineFieldIndex,
final,
enum_index++);
descriptors->Set(3, &field);
}
{
// ECMA-262, section 15.10.7.5.
PropertyAttributes writable =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
FieldDescriptor field(Heap::last_index_symbol(),
JSRegExp::kLastIndexFieldIndex,
writable,
enum_index++);
descriptors->Set(4, &field);
}
descriptors->SetNextEnumerationIndex(enum_index);
descriptors->Sort();
initial_map->set_inobject_properties(5);
initial_map->set_pre_allocated_property_fields(5);
initial_map->set_unused_property_fields(0);
initial_map->set_instance_size(
initial_map->instance_size() + 5 * kPointerSize);
initial_map->set_instance_descriptors(*descriptors);
}
{ // -- J S O N
......
......@@ -149,6 +149,11 @@ class ZoneScopeInfo;
V(number_symbol, "number") \
V(Number_symbol, "Number") \
V(RegExp_symbol, "RegExp") \
V(source_symbol, "source") \
V(global_symbol, "global") \
V(ignore_case_symbol, "ignoreCase") \
V(multiline_symbol, "multiline") \
V(last_index_symbol, "lastIndex") \
V(object_symbol, "object") \
V(prototype_symbol, "prototype") \
V(string_symbol, "string") \
......
......@@ -3667,6 +3667,13 @@ class JSRegExp: public JSObject {
FixedArray::kHeaderSize + kIrregexpUC16CodeIndex * kPointerSize;
static const int kIrregexpCaptureCountOffset =
FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize;
// In-object fields.
static const int kSourceFieldIndex = 0;
static const int kGlobalFieldIndex = 1;
static const int kIgnoreCaseFieldIndex = 2;
static const int kMultilineFieldIndex = 3;
static const int kLastIndexFieldIndex = 4;
};
......
......@@ -71,32 +71,10 @@ function DoConstructRegExp(object, pattern, flags, isConstructorCall) {
}
}
if (isConstructorCall) {
// ECMA-262, section 15.10.7.1.
%SetProperty(object, 'source', pattern,
DONT_DELETE | READ_ONLY | DONT_ENUM);
// ECMA-262, section 15.10.7.2.
%SetProperty(object, 'global', global, DONT_DELETE | READ_ONLY | DONT_ENUM);
// ECMA-262, section 15.10.7.3.
%SetProperty(object, 'ignoreCase', ignoreCase,
DONT_DELETE | READ_ONLY | DONT_ENUM);
// ECMA-262, section 15.10.7.4.
%SetProperty(object, 'multiline', multiline,
DONT_DELETE | READ_ONLY | DONT_ENUM);
// ECMA-262, section 15.10.7.5.
%SetProperty(object, 'lastIndex', 0, DONT_DELETE | DONT_ENUM);
} else { // RegExp is being recompiled via RegExp.prototype.compile.
%IgnoreAttributesAndSetProperty(object, 'source', pattern);
%IgnoreAttributesAndSetProperty(object, 'global', global);
%IgnoreAttributesAndSetProperty(object, 'ignoreCase', ignoreCase);
%IgnoreAttributesAndSetProperty(object, 'multiline', multiline);
%IgnoreAttributesAndSetProperty(object, 'lastIndex', 0);
if (!isConstructorCall) {
regExpCache.type = 'none';
}
%RegExpInitializeObject(object, pattern, global, ignoreCase, multiline);
// Call internal function to compile the pattern.
%RegExpCompile(object, pattern, flags);
......
......@@ -1228,6 +1228,62 @@ static Object* Runtime_RegExpExec(Arguments args) {
}
static Object* Runtime_RegExpInitializeObject(Arguments args) {
AssertNoAllocation no_alloc;
ASSERT(args.length() == 5);
CONVERT_CHECKED(JSRegExp, regexp, args[0]);
CONVERT_CHECKED(String, source, args[1]);
Object* global = args[2];
if (!global->IsTrue()) global = Heap::false_value();
Object* ignoreCase = args[3];
if (!ignoreCase->IsTrue()) ignoreCase = Heap::false_value();
Object* multiline = args[4];
if (!multiline->IsTrue()) multiline = Heap::false_value();
Map* map = regexp->map();
Object* constructor = map->constructor();
if (constructor->IsJSFunction() &&
JSFunction::cast(constructor)->initial_map() == map) {
// If we still have the original map, set in-object properties directly.
regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
// TODO(lrn): Consider skipping write barrier on booleans as well.
// Both true and false should be in oldspace at all times.
regexp->InObjectPropertyAtPut(JSRegExp::kGlobalFieldIndex, global);
regexp->InObjectPropertyAtPut(JSRegExp::kIgnoreCaseFieldIndex, ignoreCase);
regexp->InObjectPropertyAtPut(JSRegExp::kMultilineFieldIndex, multiline);
regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
Smi::FromInt(0),
SKIP_WRITE_BARRIER);
return regexp;
}
// Map has changed, so use generic, but slower, method.
PropertyAttributes final =
static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
PropertyAttributes writable =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
regexp->IgnoreAttributesAndSetLocalProperty(Heap::source_symbol(),
source,
final);
regexp->IgnoreAttributesAndSetLocalProperty(Heap::global_symbol(),
global,
final);
regexp->IgnoreAttributesAndSetLocalProperty(Heap::ignore_case_symbol(),
ignoreCase,
final);
regexp->IgnoreAttributesAndSetLocalProperty(Heap::multiline_symbol(),
multiline,
final);
regexp->IgnoreAttributesAndSetLocalProperty(Heap::last_index_symbol(),
Smi::FromInt(0),
writable);
return regexp;
}
static Object* Runtime_FinishArrayPrototypeSetup(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 1);
......
......@@ -154,6 +154,7 @@ namespace internal {
F(RegExpCompile, 3, 1) \
F(RegExpExec, 4, 1) \
F(RegExpExecMultiple, 4, 1) \
F(RegExpInitializeObject, 5, 1) \
\
/* Strings */ \
F(StringCharCodeAt, 2, 1) \
......
......@@ -70,8 +70,8 @@ function testRegExpMirror(r) {
assertEquals('regexp', mirror.type());
assertFalse(mirror.isPrimitive());
for (var p in expected_attributes) {
assertEquals(mirror.property(p).attributes(),
expected_attributes[p],
assertEquals(expected_attributes[p],
mirror.property(p).attributes(),
p + ' attributes');
}
......
......@@ -388,3 +388,51 @@ try {
assertTrue(String(e).indexOf("Stack overflow") >= 0, "overflow");
}
// Test that compile works on modified objects
var re = /re+/;
assertEquals("re+", re.source);
assertFalse(re.global);
assertFalse(re.ignoreCase);
assertFalse(re.multiline);
assertEquals(0, re.lastIndex);
re.compile("ro+", "gim");
assertEquals("ro+", re.source);
assertTrue(re.global);
assertTrue(re.ignoreCase);
assertTrue(re.multiline);
assertEquals(0, re.lastIndex);
re.lastIndex = 42;
re.someOtherProperty = 42;
re.someDeletableProperty = 42;
re[37] = 37;
re[42] = 42;
re.compile("ra+", "i");
assertEquals("ra+", re.source);
assertFalse(re.global);
assertTrue(re.ignoreCase);
assertFalse(re.multiline);
assertEquals(0, re.lastIndex);
assertEquals(42, re.someOtherProperty);
assertEquals(42, re.someDeletableProperty);
assertEquals(37, re[37]);
assertEquals(42, re[42]);
re.lastIndex = -1;
re.someOtherProperty = 37;
re[42] = 37;
assertTrue(delete re[37]);
assertTrue(delete re.someDeletableProperty);
re.compile("ri+", "gm");
assertEquals("ri+", re.source);
assertTrue(re.global);
assertFalse(re.ignoreCase);
assertTrue(re.multiline);
assertEquals(0, re.lastIndex);
assertEquals(37, re.someOtherProperty);
assertEquals(37, re[42]);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment