Parser: add usage counters for "use asm".
authormarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 30 Jun 2014 13:35:16 +0000 (13:35 +0000)
committermarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 30 Jun 2014 13:35:16 +0000 (13:35 +0000)
R=jochen@chromium.org
BUG=

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22093 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

include/v8.h
src/ast-value-factory.h
src/parser.cc
src/parser.h
test/cctest/test-parsing.cc

index 7d27029..6607c45 100644 (file)
@@ -4134,7 +4134,8 @@ class V8_EXPORT Isolate {
    * list.
    */
   enum UseCounterFeature {
-    kUseAsm = 0
+    kUseAsm = 0,
+    kUseCounterFeatureCount  // This enum value must be last.
   };
 
   typedef void (*UseCounterCallback)(Isolate* isolate,
index e70271f..4711bb4 100644 (file)
@@ -260,6 +260,7 @@ class AstValue : public ZoneObject {
   F(proto, "__proto__") \
   F(prototype, "prototype") \
   F(this, "this") \
+  F(use_asm, "use asm") \
   F(use_strict, "use strict") \
   F(value, "value")
 
index a04db36..d882c1e 100644 (file)
@@ -783,6 +783,10 @@ Parser::Parser(CompilationInfo* info)
   set_allow_generators(FLAG_harmony_generators);
   set_allow_for_of(FLAG_harmony_iteration);
   set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
+  for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
+       ++feature) {
+    use_counts_[feature] = 0;
+  }
 }
 
 
@@ -1087,11 +1091,13 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
       if ((e_stat = stat->AsExpressionStatement()) != NULL &&
           (literal = e_stat->expression()->AsLiteral()) != NULL &&
           literal->raw_value()->IsString()) {
-        // Check "use strict" directive (ES5 14.1).
+        // Check "use strict" directive (ES5 14.1) and "use asm" directive. Only
+        // one can be present.
         if (strict_mode() == SLOPPY &&
             literal->raw_value()->AsString() ==
                 ast_value_factory_->use_strict_string() &&
-            token_loc.end_pos - token_loc.beg_pos == 12) {
+            token_loc.end_pos - token_loc.beg_pos ==
+                ast_value_factory_->use_strict_string()->length() + 2) {
           // TODO(mstarzinger): Global strict eval calls, need their own scope
           // as specified in ES5 10.4.2(3). The correct fix would be to always
           // add this scope in DoParseProgram(), but that requires adaptations
@@ -1108,6 +1114,13 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
           scope_->SetStrictMode(STRICT);
           // "use strict" is the only directive for now.
           directive_prologue = false;
+        } else if (literal->raw_value()->AsString() ==
+                       ast_value_factory_->use_asm_string() &&
+                   token_loc.end_pos - token_loc.beg_pos ==
+                       ast_value_factory_->use_asm_string()->length() + 2) {
+          // Store the usage count; The actual use counter on the isolate is
+          // incremented after parsing is done.
+          ++use_counts_[v8::Isolate::kUseAsm];
         }
       } else {
         // End of the directive prologue.
@@ -3899,6 +3912,16 @@ void Parser::ThrowPendingError() {
 }
 
 
+void Parser::InternalizeUseCounts() {
+  for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
+       ++feature) {
+    for (int i = 0; i < use_counts_[feature]; ++i) {
+      isolate()->CountUsage(v8::Isolate::UseCounterFeature(feature));
+    }
+  }
+}
+
+
 // ----------------------------------------------------------------------------
 // Regular expressions
 
@@ -4840,6 +4863,9 @@ bool Parser::Parse() {
     info()->SetAstValueFactory(ast_value_factory_);
   }
   ast_value_factory_ = NULL;
+
+  InternalizeUseCounts();
+
   return (result != NULL);
 }
 
index c05b2d9..346f75f 100644 (file)
@@ -798,6 +798,8 @@ class Parser : public ParserBase<ParserTraits> {
 
   void ThrowPendingError();
 
+  void InternalizeUseCounts();
+
   Isolate* isolate_;
 
   Handle<Script> script_;
@@ -818,6 +820,8 @@ class Parser : public ParserBase<ParserTraits> {
   const AstRawString* pending_error_arg_;
   const char* pending_error_char_arg_;
   bool pending_error_is_reference_error_;
+
+  int use_counts_[v8::Isolate::kUseCounterFeatureCount];
 };
 
 
index 40679ad..8066f80 100644 (file)
@@ -2745,3 +2745,29 @@ TEST(InnerAssignment) {
     }
   }
 }
+
+namespace {
+
+int* global_use_counts = NULL;
+
+void MockUseCounterCallback(v8::Isolate* isolate,
+                            v8::Isolate::UseCounterFeature feature) {
+  ++global_use_counts[feature];
+}
+
+}
+
+
+TEST(UseAsmUseCount) {
+  i::Isolate* isolate = CcTest::i_isolate();
+  i::HandleScope scope(isolate);
+  LocalContext env;
+  int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
+  global_use_counts = use_counts;
+  CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
+  CompileRun("\"use asm\";\n"
+             "var foo = 1;\n"
+             "\"use asm\";\n"  // Only the first one counts.
+             "function bar() { \"use asm\"; var baz = 1; }");
+  CHECK_EQ(2, use_counts[v8::Isolate::kUseAsm]);
+}