ARM64: remove stack pushes without frame in RegExpExecStub.
authorulan <ulan@chromium.org>
Thu, 18 Jun 2015 15:45:17 +0000 (08:45 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 18 Jun 2015 15:45:32 +0000 (15:45 +0000)
RegExpExecStub pushes callee-saved registers without setting up a frame. This confuses the stack iterator.

Other architectures do not save these registers.

BUG=chromium:487981
LOG=NO
TEST=mjsunit/regress/regress-487981

Review URL: https://codereview.chromium.org/1183593005

Cr-Commit-Position: refs/heads/master@{#29120}

src/arm64/code-stubs-arm64.cc
test/mjsunit/regress/regress-487981.js [new file with mode: 0644]

index bd70150..cfce619 100644 (file)
@@ -2305,27 +2305,16 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
   Register last_match_info_elements = x21;
   Register code_object = x22;
 
-  // TODO(jbramley): Is it necessary to preserve these? I don't think ARM does.
-  CPURegList used_callee_saved_registers(subject,
-                                         regexp_data,
-                                         last_match_info_elements,
-                                         code_object);
-  __ PushCPURegList(used_callee_saved_registers);
-
   // Stack frame.
-  //  jssp[0] : x19
-  //  jssp[8] : x20
-  //  jssp[16]: x21
-  //  jssp[24]: x22
-  //  jssp[32]: last_match_info (JSArray)
-  //  jssp[40]: previous index
-  //  jssp[48]: subject string
-  //  jssp[56]: JSRegExp object
-
-  const int kLastMatchInfoOffset = 4 * kPointerSize;
-  const int kPreviousIndexOffset = 5 * kPointerSize;
-  const int kSubjectOffset = 6 * kPointerSize;
-  const int kJSRegExpOffset = 7 * kPointerSize;
+  //  jssp[00]: last_match_info (JSArray)
+  //  jssp[08]: previous index
+  //  jssp[16]: subject string
+  //  jssp[24]: JSRegExp object
+
+  const int kLastMatchInfoOffset = 0 * kPointerSize;
+  const int kPreviousIndexOffset = 1 * kPointerSize;
+  const int kSubjectOffset = 2 * kPointerSize;
+  const int kJSRegExpOffset = 3 * kPointerSize;
 
   // Ensure that a RegExp stack is allocated.
   ExternalReference address_of_regexp_stack_memory_address =
@@ -2692,7 +2681,6 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
 
   // Return last match info.
   __ Peek(x0, kLastMatchInfoOffset);
-  __ PopCPURegList(used_callee_saved_registers);
   // Drop the 4 arguments of the stub from the stack.
   __ Drop(4);
   __ Ret();
@@ -2715,13 +2703,11 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
 
   __ Bind(&failure);
   __ Mov(x0, Operand(isolate()->factory()->null_value()));
-  __ PopCPURegList(used_callee_saved_registers);
   // Drop the 4 arguments of the stub from the stack.
   __ Drop(4);
   __ Ret();
 
   __ Bind(&runtime);
-  __ PopCPURegList(used_callee_saved_registers);
   __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
 
   // Deferred code for string handling.
diff --git a/test/mjsunit/regress/regress-487981.js b/test/mjsunit/regress/regress-487981.js
new file mode 100644 (file)
index 0000000..829c25c
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags:  --allow-natives-syntax --stress-compaction
+
+// To reliably reproduce the crash use --verify-heap --random-seed=-133185440
+
+function __f_2(o) {
+  return o.field.b.x;
+}
+
+try {
+  %OptimizeFunctionOnNextCall(__f_2);
+  __v_1 = __f_2();
+} catch(e) { }
+
+function __f_3() { __f_3(/./.test()); };
+
+try {
+__f_3();
+} catch(e) { }