| Index: src/arm/codegen-arm.cc
|
| diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
|
| index f06b79bd0ccd6b05f53ca66e241d3e2f7294dae5..4bcf1a07df9c990c01d1ec413758011b0ce0d5de 100644
|
| --- a/src/arm/codegen-arm.cc
|
| +++ b/src/arm/codegen-arm.cc
|
| @@ -3280,13 +3280,13 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
|
| FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
|
| __ ldr(literal, FieldMemOperand(tmp, literal_offset));
|
|
|
| - JumpTarget done;
|
| + JumpTarget materialized;
|
| __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
|
| __ cmp(literal, ip);
|
| // This branch locks the virtual frame at the done label to match the
|
| // one we have here, where the literal register is not on the stack and
|
| // nothing is spilled.
|
| - done.Branch(ne);
|
| + materialized.Branch(ne);
|
|
|
| // If the entry is undefined we call the runtime system to compute
|
| // the literal.
|
| @@ -3301,11 +3301,23 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
|
| frame_->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
|
| __ Move(literal, r0);
|
|
|
| - // This call to bind will get us back to the virtual frame we had before
|
| - // where things are not spilled and the literal register is not on the stack.
|
| - done.Bind();
|
| - // Push the literal.
|
| + materialized.Bind();
|
| +
|
| frame_->EmitPush(literal);
|
| + int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
|
| + frame_->EmitPush(Operand(Smi::FromInt(size)));
|
| + frame_->CallRuntime(Runtime::kAllocateInNewSpace, 1);
|
| + // TODO(lrn): Use AllocateInNewSpace macro with fallback to runtime.
|
| + // r0 is newly allocated space.
|
| +
|
| + // Reuse literal variable with (possibly) a new register, still holding
|
| + // the materialized boilerplate.
|
| + literal = frame_->PopToRegister(r0);
|
| +
|
| + __ CopyFields(r0, literal, tmp.bit(), size / kPointerSize);
|
| +
|
| + // Push the clone.
|
| + frame_->EmitPush(r0);
|
| ASSERT_EQ(original_height + 1, frame_->height());
|
| }
|
|
|
| @@ -5324,6 +5336,44 @@ void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
|
| }
|
|
|
|
|
| +void CodeGenerator::GenerateIsRegExpEquivalent(ZoneList<Expression*>* args) {
|
| + ASSERT(args->length() == 2);
|
| +
|
| + // Load the two objects into registers and perform the comparison.
|
| + Load(args->at(0));
|
| + Load(args->at(1));
|
| + Register right = frame_->PopToRegister();
|
| + Register left = frame_->PopToRegister(right);
|
| + Register tmp = frame_->scratch0();
|
| + Register tmp2 = frame_->scratch1();
|
| +
|
| + // Jumps to done must have the eq flag set if the test is successful
|
| + // and clear if the test has failed.
|
| + Label done;
|
| +
|
| + // Fail if either is a non-HeapObject.
|
| + __ cmp(left, Operand(right));
|
| + __ b(eq, &done);
|
| + __ and_(tmp, left, Operand(right));
|
| + __ eor(tmp, tmp, Operand(kSmiTagMask));
|
| + __ tst(tmp, Operand(kSmiTagMask));
|
| + __ b(ne, &done);
|
| + __ ldr(tmp, FieldMemOperand(left, HeapObject::kMapOffset));
|
| + __ ldrb(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset));
|
| + __ cmp(tmp2, Operand(JS_REGEXP_TYPE));
|
| + __ b(ne, &done);
|
| + __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
|
| + __ cmp(tmp, Operand(tmp2));
|
| + __ b(ne, &done);
|
| + __ ldr(tmp, FieldMemOperand(left, JSRegExp::kDataOffset));
|
| + __ ldr(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset));
|
| + __ cmp(tmp, tmp2);
|
| + __ bind(&done);
|
| + cc_reg_ = eq;
|
| +}
|
| +
|
| +
|
| +
|
| void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
|
| #ifdef DEBUG
|
| int original_height = frame_->height();
|
| @@ -6908,10 +6958,7 @@ void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
|
| __ str(r2, FieldMemOperand(r0, JSArray::kElementsOffset));
|
|
|
| // Copy the elements array.
|
| - for (int i = 0; i < elements_size; i += kPointerSize) {
|
| - __ ldr(r1, FieldMemOperand(r3, i));
|
| - __ str(r1, FieldMemOperand(r2, i));
|
| - }
|
| + __ CopyFields(r2, r3, r1.bit(), elements_size / kPointerSize);
|
| }
|
|
|
| // Return and remove the on-stack parameters.
|
| @@ -9780,10 +9827,7 @@ void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
|
| __ ldr(r4, MemOperand(r4, offset));
|
|
|
| // Copy the JS object part.
|
| - for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
|
| - __ ldr(r3, FieldMemOperand(r4, i));
|
| - __ str(r3, FieldMemOperand(r0, i));
|
| - }
|
| + __ CopyFields(r0, r4, r3.bit(), JSObject::kHeaderSize / kPointerSize);
|
|
|
| // Setup the callee in-object property.
|
| STATIC_ASSERT(Heap::arguments_callee_index == 0);
|
|
|