Reviewers: Yang,

Description:
Allow inlining of functions containing RegExp literals.

[email protected]
BUG=v8:1322
TEST=mjsunit/compiler/inline-literals


Please review this at https://chromiumcodereview.appspot.com/10703005/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/arm/lithium-codegen-arm.cc
  M src/ast.cc
  M src/hydrogen-instructions.h
  M src/hydrogen.cc
  M src/ia32/lithium-codegen-ia32.cc
  M src/mips/lithium-codegen-mips.cc
  M src/objects-printer.cc
  M src/x64/lithium-codegen-x64.cc
  M test/mjsunit/compiler/inline-literals.js


Index: src/arm/lithium-codegen-arm.cc
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 8cef74d67aa95d79d80e05e8b0d5d5b02d9a5705..a61e4c0c5144e21f6f062b550f142ead8caa88e4 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -4987,15 +4987,13 @@ void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
   Label materialized;
   // Registers will be used as follows:
-  // r3 = JS function.
   // r7 = literals array.
   // r1 = regexp literal.
   // r0 = regexp literal clone.
   // r2 and r4-r6 are used as temporaries.
-  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ ldr(r7, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
-  int literal_offset = FixedArray::kHeaderSize +
-      instr->hydrogen()->literal_index() * kPointerSize;
+  int literal_offset =
+      FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
+  __ LoadHeapObject(r7, instr->hydrogen()->literals());
   __ ldr(r1, FieldMemOperand(r7, literal_offset));
   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
   __ cmp(r1, ip);
Index: src/ast.cc
diff --git a/src/ast.cc b/src/ast.cc
index fb9db7cda209199fca38da5c3205e009fdd10780..013c6331da4ccf994bff6134fe2cec3e6b44659f 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -1047,6 +1047,7 @@ REGULAR_NODE(SwitchStatement)
 REGULAR_NODE(Conditional)
 REGULAR_NODE(Literal)
 REGULAR_NODE(ObjectLiteral)
+REGULAR_NODE(RegExpLiteral)
 REGULAR_NODE(Assignment)
 REGULAR_NODE(Throw)
 REGULAR_NODE(Property)
@@ -1077,7 +1078,6 @@ DONT_OPTIMIZE_NODE(DebuggerStatement)
 DONT_OPTIMIZE_NODE(SharedFunctionInfoLiteral)

 DONT_INLINE_NODE(FunctionLiteral)
-DONT_INLINE_NODE(RegExpLiteral) // TODO(1322): Allow materialized literals.
 DONT_INLINE_NODE(ArrayLiteral)  // TODO(1322): Allow materialized literals.

 DONT_SELFOPTIMIZE_NODE(DoWhileStatement)
Index: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index e0c443a6c378c9f9352868a73a985a590a2591f7..e92d747f54c179cc05cbd779ffd8b3c411d52486 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -4792,10 +4792,12 @@ class HObjectLiteral: public HMaterializedLiteral<1> {
 class HRegExpLiteral: public HMaterializedLiteral<1> {
  public:
   HRegExpLiteral(HValue* context,
+                 Handle<FixedArray> literals,
                  Handle<String> pattern,
                  Handle<String> flags,
                  int literal_index)
       : HMaterializedLiteral<1>(literal_index, 0),
+        literals_(literals),
         pattern_(pattern),
         flags_(flags) {
     SetOperandAt(0, context);
@@ -4803,6 +4805,7 @@ class HRegExpLiteral: public HMaterializedLiteral<1> {
   }

   HValue* context() { return OperandAt(0); }
+  Handle<FixedArray> literals() { return literals_; }
   Handle<String> pattern() { return pattern_; }
   Handle<String> flags() { return flags_; }

@@ -4814,6 +4817,7 @@ class HRegExpLiteral: public HMaterializedLiteral<1> {
   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)

  private:
+  Handle<FixedArray> literals_;
   Handle<String> pattern_;
   Handle<String> flags_;
 };
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index e91965ebbe8af126f2991046b04fa80a292594db..0766760deef055742038f27eebf3bd5988a12680 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -4646,9 +4646,12 @@ void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
+ Handle<JSFunction> closure = function_state()->compilation_info()->closure();
+  Handle<FixedArray> literals(closure->literals());
   HValue* context = environment()->LookupContext();

   HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context,
+                                                     literals,
                                                      expr->pattern(),
                                                      expr->flags(),
expr->literal_index());
Index: src/ia32/lithium-codegen-ia32.cc
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index e27a32628ea69ed015cb984d276b056847dfb9af..9cc67a308af2584cdce9d649b8fb02294f68b829 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -4930,15 +4930,13 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
   ASSERT(ToRegister(instr->context()).is(esi));
   Label materialized;
   // Registers will be used as follows:
-  // edi = JS function.
   // ecx = literals array.
   // ebx = regexp literal.
   // eax = regexp literal clone.
   // esi = context.
-  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-  __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset));
-  int literal_offset = FixedArray::kHeaderSize +
-      instr->hydrogen()->literal_index() * kPointerSize;
+  int literal_offset =
+      FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
+  __ LoadHeapObject(ecx, instr->hydrogen()->literals());
   __ mov(ebx, FieldOperand(ecx, literal_offset));
   __ cmp(ebx, factory()->undefined_value());
   __ j(not_equal, &materialized, Label::kNear);
Index: src/mips/lithium-codegen-mips.cc
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 584fd7aa62d53eadf87f5f5ee90faea57f7fb53c..60df710dbf119e043db163cc13a01e6fae54e156 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -4759,15 +4759,13 @@ void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
   Label materialized;
   // Registers will be used as follows:
-  // a3 = JS function.
   // t3 = literals array.
   // a1 = regexp literal.
   // a0 = regexp literal clone.
   // a2 and t0-t2 are used as temporaries.
-  __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ lw(t3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
-  int literal_offset = FixedArray::kHeaderSize +
-      instr->hydrogen()->literal_index() * kPointerSize;
+  int literal_offset =
+      FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
+  __ LoadHeapObject(t3, instr->hydrogen()->literals());
   __ lw(a1, FieldMemOperand(t3, literal_offset));
   __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
   __ Branch(&materialized, ne, a1, Operand(at));
Index: src/objects-printer.cc
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index ac3765e65dbd146ca4c26924970b1b9d97ccc22c..2e58c0949e5020c85008cc9621f4a071a3b2f82e 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -739,6 +739,8 @@ void JSFunction::JSFunctionPrint(FILE* out) {
   shared()->name()->Print(out);
   PrintF(out, "\n - context = ");
   unchecked_context()->ShortPrint(out);
+  PrintF(out, "\n - literals = ");
+  literals()->ShortPrint(out);
   PrintF(out, "\n - code = ");
   code()->ShortPrint(out);
   PrintF(out, "\n");
Index: src/x64/lithium-codegen-x64.cc
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 808c4d87355f3626d5829df45f62745d893f236c..77cb75dbf243586beab9b83f9d5a142cced922e8 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -4630,14 +4630,12 @@ void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
   Label materialized;
   // Registers will be used as follows:
-  // rdi = JS function.
   // rcx = literals array.
   // rbx = regexp literal.
   // rax = regexp literal clone.
-  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
-  __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
-  int literal_offset = FixedArray::kHeaderSize +
-      instr->hydrogen()->literal_index() * kPointerSize;
+  int literal_offset =
+      FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
+  __ LoadHeapObject(rcx, instr->hydrogen()->literals());
   __ movq(rbx, FieldOperand(rcx, literal_offset));
   __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
   __ j(not_equal, &materialized, Label::kNear);
Index: test/mjsunit/compiler/inline-literals.js
diff --git a/test/mjsunit/compiler/inline-literals.js b/test/mjsunit/compiler/inline-literals.js index f78abe82d16aa795be48375adc08fc86db02f3ad..ece1ad7a25ae24bd6fb3e364adbb87801f26a393 100644
--- a/test/mjsunit/compiler/inline-literals.js
+++ b/test/mjsunit/compiler/inline-literals.js
@@ -48,3 +48,22 @@ TestObjectLiteral(1, 2, 3);
 %OptimizeFunctionOnNextCall(TestObjectLiteral);
 TestObjectLiteral(1, 2, 3);
 TestObjectLiteral('a', 'b', 'c');
+
+function r2(s, x, y) {
+  return s.replace(/a/, x + y);
+}
+
+function r1(s, x, y) {
+  return r2(s, x, y).replace(/b/, y + x);
+}
+
+function TestRegExpLiteral(s, x, y, expected) {
+  var result = r1(s, x, y);
+  assertEquals(expected, result, "TestRegExpLiteral");
+}
+
+TestRegExpLiteral("a-", "reg", "exp", "regexp-");
+TestRegExpLiteral("-b", "reg", "exp", "-expreg");
+%OptimizeFunctionOnNextCall(TestRegExpLiteral);
+TestRegExpLiteral("ab", "reg", "exp", "regexpexpreg");
+TestRegExpLiteral("ab", 12345, 54321, "6666666666");


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to