| Index: src/ia32/full-codegen-ia32.cc
|
| diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
|
| index 8f20108b1068f8eeb3abac7419c0f207a0122d23..d68d8cc8886f2e0c09d4d780ddc7991e2cdaecbb 100644
|
| --- a/src/ia32/full-codegen-ia32.cc
|
| +++ b/src/ia32/full-codegen-ia32.cc
|
| @@ -1196,27 +1196,54 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
|
|
|
| void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
| Comment cmnt(masm_, "[ RegExpLiteral");
|
| - Label done;
|
| + Label materialized;
|
| // Registers will be used as follows:
|
| // edi = JS function.
|
| - // ebx = literals array.
|
| - // eax = regexp literal.
|
| + // ecx = literals array.
|
| + // ebx = regexp literal.
|
| + // eax = regexp literal clone.
|
| __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
| - __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset));
|
| + __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset));
|
| int literal_offset =
|
| FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
|
| - __ mov(eax, FieldOperand(ebx, literal_offset));
|
| - __ cmp(eax, Factory::undefined_value());
|
| - __ j(not_equal, &done);
|
| + __ mov(ebx, FieldOperand(ecx, literal_offset));
|
| + __ cmp(ebx, Factory::undefined_value());
|
| + __ j(not_equal, &materialized);
|
| +
|
| // Create regexp literal using runtime function
|
| // Result will be in eax.
|
| - __ push(ebx);
|
| + __ push(ecx);
|
| __ push(Immediate(Smi::FromInt(expr->literal_index())));
|
| __ push(Immediate(expr->pattern()));
|
| __ push(Immediate(expr->flags()));
|
| __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
|
| - // Label done:
|
| - __ bind(&done);
|
| + __ mov(ebx, eax);
|
| +
|
| + __ bind(&materialized);
|
| + int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
|
| + Label allocated, runtime_allocate;
|
| + __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
|
| + __ jmp(&allocated);
|
| +
|
| + __ bind(&runtime_allocate);
|
| + __ push(ebx);
|
| + __ push(Immediate(Smi::FromInt(size)));
|
| + __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
|
| + __ pop(ebx);
|
| +
|
| + __ bind(&allocated);
|
| + // Copy the content into the newly allocated memory.
|
| + // (Unroll copy loop once for better throughput).
|
| + for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
|
| + __ mov(edx, FieldOperand(ebx, i));
|
| + __ mov(ecx, FieldOperand(ebx, i + kPointerSize));
|
| + __ mov(FieldOperand(eax, i), edx);
|
| + __ mov(FieldOperand(eax, i + kPointerSize), ecx);
|
| + }
|
| + if ((size % (2 * kPointerSize)) != 0) {
|
| + __ mov(edx, FieldOperand(ebx, size - kPointerSize));
|
| + __ mov(FieldOperand(eax, size - kPointerSize), edx);
|
| + }
|
| Apply(context_, eax);
|
| }
|
|
|
| @@ -2650,6 +2677,45 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
|
| }
|
|
|
|
|
| +void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
|
| + ASSERT_EQ(2, args->length());
|
| +
|
| + Register right = eax;
|
| + Register left = ebx;
|
| + Register tmp = ecx;
|
| +
|
| + VisitForValue(args->at(0), kStack);
|
| + VisitForValue(args->at(1), kAccumulator);
|
| + __ pop(left);
|
| +
|
| + Label done, fail, ok;
|
| + __ cmp(left, Operand(right));
|
| + __ j(equal, &ok);
|
| + // Fail if either is a non-HeapObject.
|
| + __ mov(tmp, left);
|
| + __ and_(Operand(tmp), right);
|
| + __ test(Operand(tmp), Immediate(kSmiTagMask));
|
| + __ j(zero, &fail);
|
| + __ mov(tmp, FieldOperand(left, HeapObject::kMapOffset));
|
| + __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset),
|
| + static_cast<int8_t>(JS_REGEXP_TYPE));
|
| + __ j(not_equal, &fail);
|
| + __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset));
|
| + __ j(not_equal, &fail);
|
| + __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset));
|
| + __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset));
|
| + __ j(equal, &ok);
|
| + __ bind(&fail);
|
| + __ mov(eax, Immediate(Factory::false_value()));
|
| + __ jmp(&done);
|
| + __ bind(&ok);
|
| + __ mov(eax, Immediate(Factory::true_value()));
|
| + __ bind(&done);
|
| +
|
| + Apply(context_, eax);
|
| +}
|
| +
|
| +
|
| void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
| Handle<String> name = expr->name();
|
| if (name->length() > 0 && name->Get(0) == '_') {
|
|
|