Index: src/x64/codegen-x64.cc |
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc |
index 688cd4d75b879f29ce1cbe5421051435f3fdfa93..b6256faf8698cde25436e462c7c5981dd6315b48 100644 |
--- a/src/x64/codegen-x64.cc |
+++ b/src/x64/codegen-x64.cc |
@@ -4813,6 +4813,30 @@ void DeferredRegExpLiteral::Generate() { |
} |
+class DeferredAllocateInNewSpace: public DeferredCode { |
+ public: |
+ DeferredAllocateInNewSpace(int size, Register target) |
+ : size_(size), target_(target) { |
+ ASSERT(size >= kPointerSize && size <= Heap::MaxObjectSizeInNewSpace()); |
+ set_comment("[ DeferredAllocateInNewSpace"); |
+ } |
+ void Generate(); |
+ |
+ private: |
+ int size_; |
+ Register target_; |
+}; |
+ |
+ |
+void DeferredAllocateInNewSpace::Generate() { |
+ __ Push(Smi::FromInt(size_)); |
+ __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
+ if (!target_.is(rax)) { |
+ __ movq(target_, rax); |
+ } |
+} |
+ |
+ |
void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { |
Comment cmnt(masm_, "[ RegExp Literal"); |
@@ -4842,10 +4866,33 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { |
__ CompareRoot(boilerplate.reg(), Heap::kUndefinedValueRootIndex); |
deferred->Branch(equal); |
deferred->BindExit(); |
- literals.Unuse(); |
- // Push the boilerplate object. |
+ // Register of boilerplate contains RegExp object. |
+ |
+ Result tmp = allocator()->Allocate(); |
+ ASSERT(tmp.is_valid()); |
+ |
+ int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
+ |
+ DeferredAllocateInNewSpace* allocate_fallback = |
+ new DeferredAllocateInNewSpace(size, literals.reg()); |
frame_->Push(&boilerplate); |
+ frame_->SpillTop(); |
+ __ AllocateInNewSpace(size, |
+ literals.reg(), |
+ tmp.reg(), |
+ no_reg, |
+ allocate_fallback->entry_label(), |
+ TAG_OBJECT); |
+ allocate_fallback->BindExit(); |
+ boilerplate = frame_->Pop(); |
+ // Copy from boilerplate to clone and return clone. |
+ |
+ for (int i = 0; i < size; i += kPointerSize) { |
+ __ movq(tmp.reg(), FieldOperand(boilerplate.reg(), i)); |
+ __ movq(FieldOperand(literals.reg(), i), tmp.reg()); |
+ } |
+ frame_->Push(&literals); |
} |
@@ -7014,6 +7061,40 @@ void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { |
} |
+void CodeGenerator::GenerateIsRegExpEquivalent(ZoneList<Expression*>* args) { |
+ ASSERT_EQ(2, args->length()); |
+ Load(args->at(0)); |
+ Load(args->at(1)); |
+ Result right_res = frame_->Pop(); |
+ Result left_res = frame_->Pop(); |
+ right_res.ToRegister(); |
+ left_res.ToRegister(); |
+ Result tmp_res = allocator()->Allocate(); |
+ ASSERT(tmp_res.is_valid()); |
+ Register right = right_res.reg(); |
+ Register left = left_res.reg(); |
+ Register tmp = tmp_res.reg(); |
+ right_res.Unuse(); |
+ left_res.Unuse(); |
+ tmp_res.Unuse(); |
+ __ cmpq(left, right); |
+ destination()->true_target()->Branch(equal); |
+ // Fail if either is a non-HeapObject. |
+ Condition either_smi = |
+ masm()->CheckEitherSmi(left, right, tmp); |
+ destination()->false_target()->Branch(either_smi); |
+ __ movq(tmp, FieldOperand(left, HeapObject::kMapOffset)); |
+ __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset), |
+ Immediate(JS_REGEXP_TYPE)); |
+ destination()->false_target()->Branch(not_equal); |
+ __ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset)); |
+ destination()->false_target()->Branch(not_equal); |
+ __ movq(tmp, FieldOperand(left, JSRegExp::kDataOffset)); |
+ __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset)); |
+ destination()->Split(equal); |
+} |
+ |
+ |
void CodeGenerator::VisitCallRuntime(CallRuntime* node) { |
if (CheckForInlineRuntimeCall(node)) { |
return; |