Reviewers: Lasse Reichstein, Mads Ager,

Message:
Implementing FastNewClosureStub for strict mode functions.
The FastNewClosureStub is parametrized via strict/non-strict mode and during
codegen it decides which map to use depending on strict-ness. The strict-ness is
also part of the hash function so the stubs do not get confused.

Thank you!
Martin


http://codereview.chromium.org/6677036/diff/1/src/bootstrapper.cc
File src/bootstrapper.cc (right):

http://codereview.chromium.org/6677036/diff/1/src/bootstrapper.cc#newcode568
src/bootstrapper.cc:568:
For some reason this felt cleaner, to freeze first and then install...

http://codereview.chromium.org/6677036/diff/1/src/contexts.h
File src/contexts.h (right):

http://codereview.chromium.org/6677036/diff/1/src/contexts.h#newcode81
src/contexts.h:81: V(FUNCTION_MAP_STRICT_INDEX, Map,
function_map_strict) \
Changing the names to end with _INDEX like all the rest.

Description:
Fast path for strict closure creation.

BUG=http://code.google.com/p/v8/issues/detail?id=1249
TEST=strict-mode.js


Please review this at http://codereview.chromium.org/6677036/

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

Affected files:
  M src/arm/code-stubs-arm.cc
  M src/arm/codegen-arm.cc
  M src/arm/full-codegen-arm.cc
  M src/arm/lithium-codegen-arm.cc
  M src/bootstrapper.cc
  M src/code-stubs.h
  M src/contexts.h
  M src/ia32/code-stubs-ia32.cc
  M src/ia32/codegen-ia32.cc
  M src/ia32/full-codegen-ia32.cc
  M src/ia32/lithium-codegen-ia32.cc
  M src/x64/code-stubs-x64.cc
  M src/x64/codegen-x64.cc
  M src/x64/full-codegen-x64.cc
  M src/x64/lithium-codegen-x64.cc


Index: src/arm/code-stubs-arm.cc
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index c45b6ab3ccd9679e1ad5f0ac0447aa3c9bf21375..fa9d4e86993aae1895fed00638343e0f81d7205d 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -91,11 +91,15 @@ void FastNewClosureStub::Generate(MacroAssembler* masm) {
                         &gc,
                         TAG_OBJECT);

+  int map_index = strict_mode_ == kStrictMode
+      ? Context::FUNCTION_MAP_STRICT_INDEX
+      : Context::FUNCTION_MAP_INDEX;
+
   // Compute the function map in the current global context and set that
   // as the map of the allocated object.
   __ ldr(r2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset));
- __ ldr(r2, MemOperand(r2, Context::SlotOffset(Context::FUNCTION_MAP_INDEX)));
+  __ ldr(r2, MemOperand(r2, Context::SlotOffset(map_index)));
   __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset));

   // Initialize the rest of the function. We don't have to update the
Index: src/arm/codegen-arm.cc
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 2a69d28de96dbd0b4ca8fe030c2e81e500ec1c12..8855cb3792881a8872bd47632f608e5a078ef6f6 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -3114,9 +3114,9 @@ void CodeGenerator::InstantiateFunction(
   // space for nested functions that don't need literals cloning.
   if (!pretenure &&
       scope()->is_function_scope() &&
-      function_info->num_literals() == 0 &&
- !function_info->strict_mode()) { // Strict mode functions use slow path.
-    FastNewClosureStub stub;
+      function_info->num_literals() == 0) {
+    FastNewClosureStub stub(
+        function_info->strict_mode() ? kStrictMode : kNonStrictMode);
     frame_->EmitPush(Operand(function_info));
     frame_->SpillAll();
     frame_->CallStub(&stub, 1);
Index: src/arm/full-codegen-arm.cc
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index b64d9930ba4d219001d7be72cbbd8169fa1c0255..dbc0dc6e74b7afe8863aa2048fa478cf8cbd7cfd 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -1086,9 +1086,8 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
       !FLAG_prepare_always_opt &&
       !pretenure &&
       scope()->is_function_scope() &&
-      info->num_literals() == 0 &&
-      !info->strict_mode()) {  // Strict mode functions use slow path.
-    FastNewClosureStub stub;
+      info->num_literals() == 0) {
+ FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode);
     __ mov(r0, Operand(info));
     __ push(r0);
     __ CallStub(&stub);
Index: src/arm/lithium-codegen-arm.cc
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index db5f99097206cec9b47c66f2effd6249a703dcc7..3143d04619d62303339220e45cfdcc34d0248628 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -3717,9 +3717,9 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   // space for nested functions that don't need literals cloning.
   Handle<SharedFunctionInfo> shared_info = instr->shared_info();
   bool pretenure = instr->hydrogen()->pretenure();
-  if (!pretenure && shared_info->num_literals() == 0 &&
- !shared_info->strict_mode()) { // Strict mode functions use slow path.
-    FastNewClosureStub stub;
+  if (!pretenure && shared_info->num_literals() == 0) {
+    FastNewClosureStub stub(
+        shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
     __ mov(r1, Operand(shared_info));
     __ push(r1);
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
Index: src/bootstrapper.cc
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 246428680ef8eee5676376b1d03c49127fb0a833..34df431372570abb4f0249b608544bae1adf412d 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -564,11 +564,11 @@ void Genesis::CreateThrowTypeErrorCallbacks(
   pill->shared()->set_code(*code);
   pill->shared()->DontAdaptArguments();

+  PreventExtensions(pill);
+
   // Install the poison pills into the calbacks array.
   callbacks->set(0, *pill);
   callbacks->set(1, *pill);
-
-  PreventExtensions(pill);
 }


Index: src/code-stubs.h
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 6af45d54faf08f83ad9295f9f35c5ee2816054dc..464d7c0b7737c4db805ada94c930b8e29e0bc4e8 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -277,12 +277,17 @@ class ToNumberStub: public CodeStub {

 class FastNewClosureStub : public CodeStub {
  public:
+  FastNewClosureStub(StrictModeFlag strict_mode)
+    : strict_mode_(strict_mode) { }
+
   void Generate(MacroAssembler* masm);

  private:
   const char* GetName() { return "FastNewClosureStub"; }
   Major MajorKey() { return FastNewClosure; }
-  int MinorKey() { return 0; }
+  int MinorKey() { return strict_mode_; }
+
+  StrictModeFlag strict_mode_;
 };


Index: src/contexts.h
diff --git a/src/contexts.h b/src/contexts.h
index 01dd933902c4c8b2e1c5bf6e32255c6d271434ec..06daf62de1bc8a40914f0a688dba4fe7449b9670 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -78,12 +78,12 @@ enum ContextLookupFlags {
   V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \
   V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \
   V(FUNCTION_MAP_INDEX, Map, function_map) \
-  V(FUNCTION_MAP_INDEX_STRICT, Map, function_map_strict) \
+  V(FUNCTION_MAP_STRICT_INDEX, Map, function_map_strict) \
V(FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, function_without_prototype_map) \
-  V(FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX_STRICT, Map, \
+  V(FUNCTION_WITHOUT_PROTOTYPE_MAP_STRICT_INDEX, Map, \
     function_without_prototype_map_strict) \
   V(FUNCTION_INSTANCE_MAP_INDEX, Map, function_instance_map) \
- V(FUNCTION_INSTANCE_MAP_INDEX_STRICT, Map, function_instance_map_strict) \ + V(FUNCTION_INSTANCE_MAP_STRICT_INDEX, Map, function_instance_map_strict) \
   V(JS_ARRAY_MAP_INDEX, Map, js_array_map)\
   V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map)\
   V(ARGUMENTS_BOILERPLATE_INDEX, JSObject, arguments_boilerplate) \
@@ -189,11 +189,11 @@ class Context: public FixedArray {
     JS_ARRAY_MAP_INDEX,
     REGEXP_RESULT_MAP_INDEX,
     FUNCTION_MAP_INDEX,
-    FUNCTION_MAP_INDEX_STRICT,
+    FUNCTION_MAP_STRICT_INDEX,
     FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
-    FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX_STRICT,
+    FUNCTION_WITHOUT_PROTOTYPE_MAP_STRICT_INDEX,
     FUNCTION_INSTANCE_MAP_INDEX,
-    FUNCTION_INSTANCE_MAP_INDEX_STRICT,
+    FUNCTION_INSTANCE_MAP_STRICT_INDEX,
     INITIAL_OBJECT_PROTOTYPE_INDEX,
     BOOLEAN_FUNCTION_INDEX,
     NUMBER_FUNCTION_INDEX,
Index: src/ia32/code-stubs-ia32.cc
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index c539ff564626c4f7b4499487c96a8e6d37593521..fd340f7f8378d9da7ae3e0ad778348b7fba0f0fd 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -69,11 +69,15 @@ void FastNewClosureStub::Generate(MacroAssembler* masm) {
   // Get the function info from the stack.
   __ mov(edx, Operand(esp, 1 * kPointerSize));

+  int map_index = strict_mode_ == kStrictMode
+      ? Context::FUNCTION_MAP_STRICT_INDEX
+      : Context::FUNCTION_MAP_INDEX;
+
   // Compute the function map in the current global context and set that
   // as the map of the allocated object.
   __ mov(ecx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset));
- __ mov(ecx, Operand(ecx, Context::SlotOffset(Context::FUNCTION_MAP_INDEX)));
+  __ mov(ecx, Operand(ecx, Context::SlotOffset(map_index)));
   __ mov(FieldOperand(eax, JSObject::kMapOffset), ecx);

   // Initialize the rest of the function. We don't have to update the
Index: src/ia32/codegen-ia32.cc
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index f7c4808ba982e697b2b743d03e245f574b3dd422..3122d0ddb362ca51d665ce38c9508c60236202d1 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -4918,9 +4918,9 @@ Result CodeGenerator::InstantiateFunction(
   // space for nested functions that don't need literals cloning.
   if (!pretenure &&
       scope()->is_function_scope() &&
-      function_info->num_literals() == 0 &&
- !function_info->strict_mode()) { // Strict mode functions use slow path.
-    FastNewClosureStub stub;
+      function_info->num_literals() == 0) {
+    FastNewClosureStub stub(
+        function_info->strict_mode() ? kStrictMode : kNonStrictMode);
     frame()->EmitPush(Immediate(function_info));
     return frame()->CallStub(&stub, 1);
   } else {
Index: src/ia32/full-codegen-ia32.cc
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 060d4ed57dc7597564b318895f6d7c15de3b6010..943ea182819f17256ba575ca5694c607f9951cd2 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -1019,9 +1019,8 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
       !FLAG_prepare_always_opt &&
       !pretenure &&
       scope()->is_function_scope() &&
-      info->num_literals() == 0 &&
- !info->strict_mode()) { // Strict mode functions go through slow path.
-    FastNewClosureStub stub;
+      info->num_literals() == 0) {
+ FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode);
     __ push(Immediate(info));
     __ CallStub(&stub);
   } else {
Index: src/ia32/lithium-codegen-ia32.cc
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 3ac9ff53a04b570c0682a36a640288f221331c08..59474785d3e681c6df7baf25deeb2472c92de82b 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -3693,9 +3693,9 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   // space for nested functions that don't need literals cloning.
   Handle<SharedFunctionInfo> shared_info = instr->shared_info();
   bool pretenure = instr->hydrogen()->pretenure();
-  if (!pretenure && shared_info->num_literals() == 0 &&
-      !shared_info->strict_mode()) {
-    FastNewClosureStub stub;
+  if (!pretenure && shared_info->num_literals() == 0) {
+    FastNewClosureStub stub(
+        shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
     __ push(Immediate(shared_info));
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false);
   } else {
Index: src/x64/code-stubs-x64.cc
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index ca78236aa2157eef69c4b9838d6272fd22ee2b4e..96ef755a1d745baa84badd5ac7547c55b536aabf 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -68,11 +68,15 @@ void FastNewClosureStub::Generate(MacroAssembler* masm) {
   // Get the function info from the stack.
   __ movq(rdx, Operand(rsp, 1 * kPointerSize));

+  int map_index = strict_mode_ == kStrictMode
+      ? Context::FUNCTION_MAP_STRICT_INDEX
+      : Context::FUNCTION_MAP_INDEX;
+
   // Compute the function map in the current global context and set that
   // as the map of the allocated object.
   __ movq(rcx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset));
- __ movq(rcx, Operand(rcx, Context::SlotOffset(Context::FUNCTION_MAP_INDEX)));
+  __ movq(rcx, Operand(rcx, Context::SlotOffset(map_index)));
   __ movq(FieldOperand(rax, JSObject::kMapOffset), rcx);

   // Initialize the rest of the function. We don't have to update the
Index: src/x64/codegen-x64.cc
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index 8074b4a38a3d7fc21b17430a6bab333e67798cdd..792efd77b0a96e32b5cdfcbc8077b3cb7aa22ad5 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -4263,9 +4263,9 @@ void CodeGenerator::InstantiateFunction(
   // space for nested functions that don't need literals cloning.
   if (!pretenure &&
       scope()->is_function_scope() &&
-      function_info->num_literals() == 0 &&
- !function_info->strict_mode()) { // Strict mode functions use slow path.
-    FastNewClosureStub stub;
+      function_info->num_literals() == 0) {
+    FastNewClosureStub stub(
+        function_info->strict_mode() ? kStrictMode : kNonStrictMode);
     frame_->Push(function_info);
     Result answer = frame_->CallStub(&stub, 1);
     frame_->Push(&answer);
Index: src/x64/full-codegen-x64.cc
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 8b148624d86b8792207fac3e3125d273299a1e8f..c4ae1cd36c1c3becdd02fc6ad9a6b1114b1e2006 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -1041,9 +1041,8 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
       !FLAG_prepare_always_opt &&
       !pretenure &&
       scope()->is_function_scope() &&
-      info->num_literals() == 0 &&
-      !info->strict_mode()) {  // Strict mode functions use slow path.
-    FastNewClosureStub stub;
+      info->num_literals() == 0) {
+ FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode);
     __ Push(info);
     __ CallStub(&stub);
   } else {
Index: src/x64/lithium-codegen-x64.cc
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 1f3b7797978cf8e0c6b43b8ed10f63b3318c2866..ce60d23670cc2c0aa1ec3c8051cb1880a2888df7 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -3496,9 +3496,9 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   // space for nested functions that don't need literals cloning.
   Handle<SharedFunctionInfo> shared_info = instr->shared_info();
   bool pretenure = instr->hydrogen()->pretenure();
-  if (!pretenure && shared_info->num_literals() == 0 &&
-      !shared_info->strict_mode()) {
-    FastNewClosureStub stub;
+  if (!pretenure && shared_info->num_literals() == 0) {
+    FastNewClosureStub stub(
+        shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
     __ Push(shared_info);
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   } else {


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

Reply via email to