Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: test/cctest/test-api-fast-accessor-builder.cc

Issue 1588053002: Generalize 'fast accessor' tests to work with --always-opt. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/test-api-accessors.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stdlib.h> 5 #include <stdlib.h>
6 6
7 #include "include/v8.h" 7 #include "include/v8.h"
8 #include "include/v8-experimental.h" 8 #include "include/v8-experimental.h"
9 9
10 #include "src/api.h" 10 #include "src/api.h"
11 #include "test/cctest/cctest.h" 11 #include "test/cctest/cctest.h"
12 12
13 namespace { 13 namespace {
14 14
15 // These tests mean to exercise v8::FastAccessorBuilder. Since initially the 15 // These tests mean to exercise v8::FastAccessorBuilder. Since initially the
16 // "native" accessor will get called, we need to 'warmup' any accessor first, 16 // "native" accessor will get called, we need to "warmup" any accessor first,
17 // to make sure we're actually testing the v8::FastAccessorBuilder result. 17 // to make sure we're actually testing the v8::FastAccessorBuilder result.
18 // To accomplish this, we will 18 // To accomplish this, we will
19 // - call each accesssor N times before the actual test. 19 // - call each accesssor N times before the actual test.
20 // - wrap that call in a function, so that all such calls will go 20 // - wrap that call in a function, so that all such calls will go
21 // through a single call site. 21 // through a single call site.
22 // - bloat that function with a very long comment to prevent its inlining.
22 // - register a native accessor which is different from the build one 23 // - register a native accessor which is different from the build one
23 // (so that our tests will always fail if we don't end up in the 'fast' 24 // (so that our tests will always fail if we don't end up in the 'fast'
24 // accessor) 25 // accessor).
25 // 26 //
26 // This doesn't work if the src function is inlined - as it is when 27 // FN_WARMUP(name, src) define a JS function "name" with body "src".
27 // --always-opt is enabled - since then every inlined functino is its own 28 // It adds the INLINE_SPOILER to prevent inlining and will call name()
28 // callsite. Hence most test will check for i::FLAG_always_opt. 29 // repeatedly to guarantee it's "warm".
29 #define WARMUP(src) "for(i = 0; i < 2; i++) { " src " } " 30 //
31 // Use:
32 // CompileRun(FN_WARMUP("fn", "return something();"));
33 // ExpectXXX("fn(1234)", 5678);
34
35 #define INLINE_SPOILER \
36 " /* " \
37 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
38 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
39 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
40 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
41 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
42 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
43 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
44 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
45 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
46 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
47 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
48 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
49 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
50 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
51 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
52 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
53 "*/ " // 16 lines * 64 'X' =~ 1024 character comment.
54 #define FN_WARMUP(name, src) \
55 "function " name "() { " src INLINE_SPOILER \
56 " }; for(i = 0; i < 2; i++) { " name "() } "
30 57
31 static void NativePropertyAccessor( 58 static void NativePropertyAccessor(
32 const v8::FunctionCallbackInfo<v8::Value>& info) { 59 const v8::FunctionCallbackInfo<v8::Value>& info) {
33 info.GetReturnValue().Set(v8_num(123)); 60 info.GetReturnValue().Set(v8_num(123));
34 } 61 }
35 62
36 } // anonymous namespace 63 } // anonymous namespace
37 64
38 65
39 // Build a simple "fast accessor" and verify that it is being called. 66 // Build a simple "fast accessor" and verify that it is being called.
40 TEST(FastAccessor) { 67 TEST(FastAccessor) {
41 if (i::FLAG_always_opt) return;
42
43 LocalContext env; 68 LocalContext env;
44 v8::Isolate* isolate = env->GetIsolate(); 69 v8::Isolate* isolate = env->GetIsolate();
45 v8::HandleScope scope(isolate); 70 v8::HandleScope scope(isolate);
46 71
47 v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate); 72 v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
48 73
49 // Native accessor, bar, returns 123. 74 // Native accessor, bar, returns 123.
50 foo->PrototypeTemplate()->SetAccessorProperty( 75 foo->PrototypeTemplate()->SetAccessorProperty(
51 v8_str("bar"), 76 v8_str("bar"),
52 v8::FunctionTemplate::New(isolate, NativePropertyAccessor)); 77 v8::FunctionTemplate::New(isolate, NativePropertyAccessor));
53 78
54 // Fast accessor, barf, returns 124. 79 // Fast accessor, barf, returns 124.
55 auto fab = v8::experimental::FastAccessorBuilder::New(isolate); 80 auto fab = v8::experimental::FastAccessorBuilder::New(isolate);
56 fab->ReturnValue(fab->IntegerConstant(124)); 81 fab->ReturnValue(fab->IntegerConstant(124));
57 foo->PrototypeTemplate()->SetAccessorProperty( 82 foo->PrototypeTemplate()->SetAccessorProperty(
58 v8_str("barf"), v8::FunctionTemplate::NewWithFastHandler( 83 v8_str("barf"), v8::FunctionTemplate::NewWithFastHandler(
59 isolate, NativePropertyAccessor, fab)); 84 isolate, NativePropertyAccessor, fab));
60 85
61 // Install foo on the global object. 86 // Install foo on the global object.
62 CHECK(env->Global() 87 CHECK(env->Global()
63 ->Set(env.local(), v8_str("foo"), 88 ->Set(env.local(), v8_str("foo"),
64 foo->GetFunction(env.local()).ToLocalChecked()) 89 foo->GetFunction(env.local()).ToLocalChecked())
65 .FromJust()); 90 .FromJust());
66 91
67 // Wrap f.barf + IC warmup. 92 // Wrap f.barf + IC warmup.
68 CompileRun( 93 CompileRun(FN_WARMUP("barf", "f = new foo(); return f.barf"));
69 "function barf() { f = new foo(); return f.barf }; " WARMUP("barf()"));
70 94
71 ExpectInt32("f = new foo(); f.bar", 123); 95 ExpectInt32("f = new foo(); f.bar", 123);
72 ExpectInt32("f = new foo(); f.barf", 123); // First call in this call site. 96 ExpectInt32("f = new foo(); f.barf", 123); // First call in this call site.
73 ExpectInt32("barf()", 124); // Call via warmed-up callsite. 97 ExpectInt32("barf()", 124); // Call via warmed-up callsite.
74 } 98 }
75 99
76 100
77 void AddInternalFieldAccessor(v8::Isolate* isolate, 101 void AddInternalFieldAccessor(v8::Isolate* isolate,
78 v8::Local<v8::Template> templ, const char* name, 102 v8::Local<v8::Template> templ, const char* name,
79 int field_no) { 103 int field_no) {
80 auto builder = v8::experimental::FastAccessorBuilder::New(isolate); 104 auto builder = v8::experimental::FastAccessorBuilder::New(isolate);
81 builder->ReturnValue( 105 builder->ReturnValue(
82 builder->LoadInternalField(builder->GetReceiver(), field_no)); 106 builder->LoadInternalField(builder->GetReceiver(), field_no));
83 templ->SetAccessorProperty(v8_str(name), 107 templ->SetAccessorProperty(v8_str(name),
84 v8::FunctionTemplate::NewWithFastHandler( 108 v8::FunctionTemplate::NewWithFastHandler(
85 isolate, NativePropertyAccessor, builder)); 109 isolate, NativePropertyAccessor, builder));
86 } 110 }
87 111
88 112
89 // "Fast" accessor that accesses an internal field. 113 // "Fast" accessor that accesses an internal field.
90 TEST(FastAccessorWithInternalField) { 114 TEST(FastAccessorWithInternalField) {
91 if (i::FLAG_always_opt) return;
92
93 LocalContext env; 115 LocalContext env;
94 v8::Isolate* isolate = env->GetIsolate(); 116 v8::Isolate* isolate = env->GetIsolate();
95 v8::HandleScope scope(isolate); 117 v8::HandleScope scope(isolate);
96 118
97 v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate); 119 v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate);
98 foo->SetInternalFieldCount(3); 120 foo->SetInternalFieldCount(3);
99 AddInternalFieldAccessor(isolate, foo, "field0", 0); 121 AddInternalFieldAccessor(isolate, foo, "field0", 0);
100 AddInternalFieldAccessor(isolate, foo, "field1", 1); 122 AddInternalFieldAccessor(isolate, foo, "field1", 1);
101 AddInternalFieldAccessor(isolate, foo, "field2", 2); 123 AddInternalFieldAccessor(isolate, foo, "field2", 2);
102 124
103 // Create an instance w/ 3 internal fields, put in a string, a Smi, nothing. 125 // Create an instance w/ 3 internal fields, put in a string, a Smi, nothing.
104 v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked(); 126 v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked();
105 obj->SetInternalField(0, v8_str("Hi there!")); 127 obj->SetInternalField(0, v8_str("Hi there!"));
106 obj->SetInternalField(1, v8::Integer::New(isolate, 4321)); 128 obj->SetInternalField(1, v8::Integer::New(isolate, 4321));
107 CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust()); 129 CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
108 130
109 // Warmup. 131 // Warmup.
110 CompileRun("function field0() { return obj.field0 }; " WARMUP("field0()")); 132 CompileRun(FN_WARMUP("field0", "return obj.field0"));
111 CompileRun("function field1() { return obj.field1 }; " WARMUP("field1()")); 133 CompileRun(FN_WARMUP("field1", "return obj.field1"));
112 CompileRun("function field2() { return obj.field2 }; " WARMUP("field2()")); 134 CompileRun(FN_WARMUP("field2", "return obj.field2"));
113 135
114 // Access fields. 136 // Access fields.
115 ExpectString("field0()", "Hi there!"); 137 ExpectString("field0()", "Hi there!");
116 ExpectInt32("field1()", 4321); 138 ExpectInt32("field1()", 4321);
117 ExpectUndefined("field2()"); 139 ExpectUndefined("field2()");
118 } 140 }
119 141
120 142
121 // "Fast" accessor with control flow via ...OrReturnNull methods. 143 // "Fast" accessor with control flow via ...OrReturnNull methods.
122 TEST(FastAccessorOrReturnNull) { 144 TEST(FastAccessorOrReturnNull) {
123 if (i::FLAG_always_opt) return;
124
125 LocalContext env; 145 LocalContext env;
126 v8::Isolate* isolate = env->GetIsolate(); 146 v8::Isolate* isolate = env->GetIsolate();
127 v8::HandleScope scope(isolate); 147 v8::HandleScope scope(isolate);
128 148
129 v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate); 149 v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate);
130 foo->SetInternalFieldCount(2); 150 foo->SetInternalFieldCount(2);
131 { 151 {
132 // accessor "nullcheck": Return null if field 0 is non-null object; else 5. 152 // accessor "nullcheck": Return null if field 0 is non-null object; else 5.
133 auto builder = v8::experimental::FastAccessorBuilder::New(isolate); 153 auto builder = v8::experimental::FastAccessorBuilder::New(isolate);
134 auto val = builder->LoadInternalField(builder->GetReceiver(), 0); 154 auto val = builder->LoadInternalField(builder->GetReceiver(), 0);
(...skipping 12 matching lines...) Expand all
147 foo->SetAccessorProperty(v8_str("maskcheck"), 167 foo->SetAccessorProperty(v8_str("maskcheck"),
148 v8::FunctionTemplate::NewWithFastHandler( 168 v8::FunctionTemplate::NewWithFastHandler(
149 isolate, NativePropertyAccessor, builder)); 169 isolate, NativePropertyAccessor, builder));
150 } 170 }
151 171
152 // Create an instance. 172 // Create an instance.
153 v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked(); 173 v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked();
154 CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust()); 174 CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
155 175
156 // CheckNotZeroOrReturnNull: 176 // CheckNotZeroOrReturnNull:
157 CompileRun( 177 CompileRun(FN_WARMUP("nullcheck", "return obj.nullcheck"));
158 "function nullcheck() { return obj.nullcheck }; " WARMUP("nullcheck()"));
159 obj->SetAlignedPointerInInternalField(0, /* anything != nullptr */ isolate); 178 obj->SetAlignedPointerInInternalField(0, /* anything != nullptr */ isolate);
160 ExpectInt32("nullcheck()", 5); 179 ExpectInt32("nullcheck()", 5);
161 obj->SetAlignedPointerInInternalField(0, nullptr); 180 obj->SetAlignedPointerInInternalField(0, nullptr);
162 ExpectNull("nullcheck()"); 181 ExpectNull("nullcheck()");
163 182
164 // CheckFlagSetOrReturnNull: 183 // CheckFlagSetOrReturnNull:
165 CompileRun( 184 CompileRun(FN_WARMUP("maskcheck", "return obj.maskcheck"));
166 "function maskcheck() { return obj.maskcheck }; " WARMUP("maskcheck()"));
167 obj->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(0xf0)); 185 obj->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(0xf0));
168 ExpectInt32("maskcheck()", 42); 186 ExpectInt32("maskcheck()", 42);
169 obj->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(0xfe)); 187 obj->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(0xfe));
170 ExpectNull("maskcheck()"); 188 ExpectNull("maskcheck()");
171 } 189 }
172 190
173 191
174 // "Fast" accessor with simple control flow via explicit labels. 192 // "Fast" accessor with simple control flow via explicit labels.
175 TEST(FastAccessorControlFlowWithLabels) { 193 TEST(FastAccessorControlFlowWithLabels) {
176 if (i::FLAG_always_opt) return;
177
178 LocalContext env; 194 LocalContext env;
179 v8::Isolate* isolate = env->GetIsolate(); 195 v8::Isolate* isolate = env->GetIsolate();
180 v8::HandleScope scope(isolate); 196 v8::HandleScope scope(isolate);
181 197
182 v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate); 198 v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate);
183 foo->SetInternalFieldCount(1); 199 foo->SetInternalFieldCount(1);
184 { 200 {
185 // accessor isnull: 0 for nullptr, else 1. 201 // accessor isnull: 0 for nullptr, else 1.
186 auto builder = v8::experimental::FastAccessorBuilder::New(isolate); 202 auto builder = v8::experimental::FastAccessorBuilder::New(isolate);
187 auto label = builder->MakeLabel(); 203 auto label = builder->MakeLabel();
188 auto val = builder->LoadInternalField(builder->GetReceiver(), 0); 204 auto val = builder->LoadInternalField(builder->GetReceiver(), 0);
189 builder->CheckNotZeroOrJump(val, label); 205 builder->CheckNotZeroOrJump(val, label);
190 builder->ReturnValue(builder->IntegerConstant(0)); 206 builder->ReturnValue(builder->IntegerConstant(0));
191 builder->SetLabel(label); 207 builder->SetLabel(label);
192 builder->ReturnValue(builder->IntegerConstant(1)); 208 builder->ReturnValue(builder->IntegerConstant(1));
193 foo->SetAccessorProperty(v8_str("isnull"), 209 foo->SetAccessorProperty(v8_str("isnull"),
194 v8::FunctionTemplate::NewWithFastHandler( 210 v8::FunctionTemplate::NewWithFastHandler(
195 isolate, NativePropertyAccessor, builder)); 211 isolate, NativePropertyAccessor, builder));
196 } 212 }
197 213
198 // Create an instance. 214 // Create an instance.
199 v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked(); 215 v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked();
200 CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust()); 216 CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
201 217
202 // CheckNotZeroOrReturnNull: 218 // CheckNotZeroOrReturnNull:
203 CompileRun("function isnull() { return obj.isnull }; " WARMUP("isnull()")); 219 CompileRun(FN_WARMUP("isnull", "return obj.isnull"));
204 obj->SetAlignedPointerInInternalField(0, /* anything != nullptr */ isolate); 220 obj->SetAlignedPointerInInternalField(0, /* anything != nullptr */ isolate);
205 ExpectInt32("isnull()", 1); 221 ExpectInt32("isnull()", 1);
206 obj->SetAlignedPointerInInternalField(0, nullptr); 222 obj->SetAlignedPointerInInternalField(0, nullptr);
207 ExpectInt32("isnull()", 0); 223 ExpectInt32("isnull()", 0);
208 } 224 }
209 225
210 226
211 // "Fast" accessor, loading things. 227 // "Fast" accessor, loading things.
212 TEST(FastAccessorLoad) { 228 TEST(FastAccessorLoad) {
213 if (i::FLAG_always_opt) return;
214
215 LocalContext env; 229 LocalContext env;
216 v8::Isolate* isolate = env->GetIsolate(); 230 v8::Isolate* isolate = env->GetIsolate();
217 v8::HandleScope scope(isolate); 231 v8::HandleScope scope(isolate);
218 232
219 v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate); 233 v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate);
220 foo->SetInternalFieldCount(1); 234 foo->SetInternalFieldCount(1);
221 235
222 // Internal field 0 is a pointer to a C++ data structure that we wish to load 236 // Internal field 0 is a pointer to a C++ data structure that we wish to load
223 // field values from. 237 // field values from.
224 struct { 238 struct {
(...skipping 29 matching lines...) Expand all
254 v8::FunctionTemplate::NewWithFastHandler( 268 v8::FunctionTemplate::NewWithFastHandler(
255 isolate, NativePropertyAccessor, builder)); 269 isolate, NativePropertyAccessor, builder));
256 } 270 }
257 271
258 // Create an instance. 272 // Create an instance.
259 v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked(); 273 v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked();
260 obj->SetAlignedPointerInInternalField(0, &val); 274 obj->SetAlignedPointerInInternalField(0, &val);
261 CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust()); 275 CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
262 276
263 // Access val.intval: 277 // Access val.intval:
264 CompileRun("function nonzero() { return obj.nonzero }; " WARMUP("nonzero()")); 278 CompileRun(FN_WARMUP("nonzero", "return obj.nonzero"));
265 ExpectInt32("nonzero()", 1); 279 ExpectInt32("nonzero()", 1);
266 val.intval = 0; 280 val.intval = 0;
267 ExpectInt32("nonzero()", 0); 281 ExpectInt32("nonzero()", 0);
268 val.intval = 27; 282 val.intval = 27;
269 ExpectInt32("nonzero()", 1); 283 ExpectInt32("nonzero()", 1);
270 284
271 // Access val.v8val: 285 // Access val.v8val:
272 CompileRun("function loadval() { return obj.loadval }; " WARMUP("loadval()")); 286 CompileRun(FN_WARMUP("loadval", "return obj.loadval"));
273 ExpectString("loadval()", "Hello"); 287 ExpectString("loadval()", "Hello");
274 } 288 }
OLDNEW
« no previous file with comments | « test/cctest/test-api-accessors.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698