1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/init/v8.h"
6 
7 #include "test/cctest/cctest.h"
8 
9 namespace v8 {
10 namespace internal {
11 namespace test_usecounters {
12 
13 int* global_use_counts = nullptr;
14 
MockUseCounterCallback(v8::Isolate * isolate,v8::Isolate::UseCounterFeature feature)15 void MockUseCounterCallback(v8::Isolate* isolate,
16                             v8::Isolate::UseCounterFeature feature) {
17   ++global_use_counts[feature];
18 }
19 
TEST(AssigmentExpressionLHSIsCall)20 TEST(AssigmentExpressionLHSIsCall) {
21   v8::Isolate* isolate = CcTest::isolate();
22   v8::HandleScope scope(isolate);
23   LocalContext env;
24   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
25   global_use_counts = use_counts;
26   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
27 
28   // AssignmentExpressions whose LHS is not a call do not increment counters
29   CompileRun("function f(){ a = 0; a()[b] = 0; }");
30   CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]);
31   CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]);
32   CompileRun("function f(){ ++a; ++a()[b]; }");
33   CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]);
34   CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]);
35   CompileRun("function f(){ 'use strict'; a = 0; a()[b] = 0; }");
36   CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]);
37   CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]);
38   CompileRun("function f(){ 'use strict'; ++a; ++a()[b]; }");
39   CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]);
40   CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]);
41 
42   // AssignmentExpressions whose LHS is a call increment appropriate counters
43   CompileRun("function f(){ a() = 0; }");
44   CHECK_NE(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]);
45   CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]);
46   use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy] = 0;
47   CompileRun("function f(){ 'use strict'; a() = 0; }");
48   CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]);
49   CHECK_NE(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]);
50   use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict] = 0;
51 
52   // UpdateExpressions whose LHS is a call increment appropriate counters
53   CompileRun("function f(){ ++a(); }");
54   CHECK_NE(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]);
55   CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]);
56   use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy] = 0;
57   CompileRun("function f(){ 'use strict'; ++a(); }");
58   CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]);
59   CHECK_NE(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]);
60   use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict] = 0;
61 }
62 
TEST(RegExpMatchIsTrueishOnNonJSRegExp)63 TEST(RegExpMatchIsTrueishOnNonJSRegExp) {
64   v8::Isolate* isolate = CcTest::isolate();
65   v8::HandleScope scope(isolate);
66   LocalContext env;
67   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
68   global_use_counts = use_counts;
69   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
70 
71   CompileRun("new RegExp(/./); new RegExp('');");
72   CHECK_EQ(0, use_counts[v8::Isolate::kRegExpMatchIsTrueishOnNonJSRegExp]);
73   CHECK_EQ(0, use_counts[v8::Isolate::kRegExpMatchIsFalseishOnJSRegExp]);
74 
75   CompileRun("let p = { [Symbol.match]: true }; new RegExp(p);");
76   CHECK_EQ(1, use_counts[v8::Isolate::kRegExpMatchIsTrueishOnNonJSRegExp]);
77   CHECK_EQ(0, use_counts[v8::Isolate::kRegExpMatchIsFalseishOnJSRegExp]);
78 }
79 
TEST(RegExpMatchIsFalseishOnJSRegExp)80 TEST(RegExpMatchIsFalseishOnJSRegExp) {
81   v8::Isolate* isolate = CcTest::isolate();
82   v8::HandleScope scope(isolate);
83   LocalContext env;
84   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
85   global_use_counts = use_counts;
86   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
87 
88   CompileRun("new RegExp(/./); new RegExp('');");
89   CHECK_EQ(0, use_counts[v8::Isolate::kRegExpMatchIsTrueishOnNonJSRegExp]);
90   CHECK_EQ(0, use_counts[v8::Isolate::kRegExpMatchIsFalseishOnJSRegExp]);
91 
92   CompileRun("let p = /./; p[Symbol.match] = false; new RegExp(p);");
93   CHECK_EQ(0, use_counts[v8::Isolate::kRegExpMatchIsTrueishOnNonJSRegExp]);
94   CHECK_EQ(1, use_counts[v8::Isolate::kRegExpMatchIsFalseishOnJSRegExp]);
95 }
96 
TEST(ObjectPrototypeHasElements)97 TEST(ObjectPrototypeHasElements) {
98   v8::Isolate* isolate = CcTest::isolate();
99   v8::HandleScope scope(isolate);
100   LocalContext env;
101   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
102   global_use_counts = use_counts;
103   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
104 
105   CompileRun("var o = {}; o[1] = 2;");
106   CHECK_EQ(0, use_counts[v8::Isolate::kObjectPrototypeHasElements]);
107 
108   CompileRun("var o = {}; var p = {}; o.__proto__ = p; p[1] = 2;");
109   CHECK_EQ(0, use_counts[v8::Isolate::kObjectPrototypeHasElements]);
110 
111   CompileRun("Object.prototype[1] = 2;");
112   CHECK_EQ(1, use_counts[v8::Isolate::kObjectPrototypeHasElements]);
113 }
114 
TEST(ArrayPrototypeHasElements)115 TEST(ArrayPrototypeHasElements) {
116   v8::Isolate* isolate = CcTest::isolate();
117   v8::HandleScope scope(isolate);
118   LocalContext env;
119   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
120   global_use_counts = use_counts;
121   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
122 
123   CompileRun("var a = []; a[1] = 2;");
124   CHECK_EQ(0, use_counts[v8::Isolate::kArrayPrototypeHasElements]);
125 
126   CompileRun("var a = []; var p = []; a.__proto__ = p; p[1] = 2;");
127   CHECK_EQ(0, use_counts[v8::Isolate::kArrayPrototypeHasElements]);
128 
129   CompileRun("Array.prototype[1] = 2;");
130   CHECK_EQ(1, use_counts[v8::Isolate::kArrayPrototypeHasElements]);
131 }
132 
133 }  // namespace test_usecounters
134 }  // namespace internal
135 }  // namespace v8
136