Index: test/cctest/test-api-fast-accessor-builder.cc |
diff --git a/test/cctest/test-api-fast-accessor-builder.cc b/test/cctest/test-api-fast-accessor-builder.cc |
index 3b38c66a598d95cc92783f4f458f3d9f8eebf58f..1e1c972694446cb304a69e82b35241ca3fac0704 100644 |
--- a/test/cctest/test-api-fast-accessor-builder.cc |
+++ b/test/cctest/test-api-fast-accessor-builder.cc |
@@ -13,20 +13,47 @@ |
namespace { |
// These tests mean to exercise v8::FastAccessorBuilder. Since initially the |
-// "native" accessor will get called, we need to 'warmup' any accessor first, |
+// "native" accessor will get called, we need to "warmup" any accessor first, |
// to make sure we're actually testing the v8::FastAccessorBuilder result. |
// To accomplish this, we will |
// - call each accesssor N times before the actual test. |
// - wrap that call in a function, so that all such calls will go |
// through a single call site. |
+// - bloat that function with a very long comment to prevent its inlining. |
// - register a native accessor which is different from the build one |
// (so that our tests will always fail if we don't end up in the 'fast' |
-// accessor) |
+// accessor). |
// |
-// This doesn't work if the src function is inlined - as it is when |
-// --always-opt is enabled - since then every inlined functino is its own |
-// callsite. Hence most test will check for i::FLAG_always_opt. |
-#define WARMUP(src) "for(i = 0; i < 2; i++) { " src " } " |
+// FN_WARMUP(name, src) define a JS function "name" with body "src". |
+// It adds the INLINE_SPOILER to prevent inlining and will call name() |
+// repeatedly to guarantee it's "warm". |
+// |
+// Use: |
+// CompileRun(FN_WARMUP("fn", "return something();")); |
+// ExpectXXX("fn(1234)", 5678); |
+ |
+#define INLINE_SPOILER \ |
+ " /* " \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ |
+ "*/ " // 16 lines * 64 'X' =~ 1024 character comment. |
+#define FN_WARMUP(name, src) \ |
+ "function " name "() { " src INLINE_SPOILER \ |
+ " }; for(i = 0; i < 2; i++) { " name "() } " |
static void NativePropertyAccessor( |
const v8::FunctionCallbackInfo<v8::Value>& info) { |
@@ -38,8 +65,6 @@ static void NativePropertyAccessor( |
// Build a simple "fast accessor" and verify that it is being called. |
TEST(FastAccessor) { |
- if (i::FLAG_always_opt) return; |
- |
LocalContext env; |
v8::Isolate* isolate = env->GetIsolate(); |
v8::HandleScope scope(isolate); |
@@ -65,8 +90,7 @@ TEST(FastAccessor) { |
.FromJust()); |
// Wrap f.barf + IC warmup. |
- CompileRun( |
- "function barf() { f = new foo(); return f.barf }; " WARMUP("barf()")); |
+ CompileRun(FN_WARMUP("barf", "f = new foo(); return f.barf")); |
ExpectInt32("f = new foo(); f.bar", 123); |
ExpectInt32("f = new foo(); f.barf", 123); // First call in this call site. |
@@ -88,8 +112,6 @@ void AddInternalFieldAccessor(v8::Isolate* isolate, |
// "Fast" accessor that accesses an internal field. |
TEST(FastAccessorWithInternalField) { |
- if (i::FLAG_always_opt) return; |
- |
LocalContext env; |
v8::Isolate* isolate = env->GetIsolate(); |
v8::HandleScope scope(isolate); |
@@ -107,9 +129,9 @@ TEST(FastAccessorWithInternalField) { |
CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust()); |
// Warmup. |
- CompileRun("function field0() { return obj.field0 }; " WARMUP("field0()")); |
- CompileRun("function field1() { return obj.field1 }; " WARMUP("field1()")); |
- CompileRun("function field2() { return obj.field2 }; " WARMUP("field2()")); |
+ CompileRun(FN_WARMUP("field0", "return obj.field0")); |
+ CompileRun(FN_WARMUP("field1", "return obj.field1")); |
+ CompileRun(FN_WARMUP("field2", "return obj.field2")); |
// Access fields. |
ExpectString("field0()", "Hi there!"); |
@@ -120,8 +142,6 @@ TEST(FastAccessorWithInternalField) { |
// "Fast" accessor with control flow via ...OrReturnNull methods. |
TEST(FastAccessorOrReturnNull) { |
- if (i::FLAG_always_opt) return; |
- |
LocalContext env; |
v8::Isolate* isolate = env->GetIsolate(); |
v8::HandleScope scope(isolate); |
@@ -154,16 +174,14 @@ TEST(FastAccessorOrReturnNull) { |
CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust()); |
// CheckNotZeroOrReturnNull: |
- CompileRun( |
- "function nullcheck() { return obj.nullcheck }; " WARMUP("nullcheck()")); |
+ CompileRun(FN_WARMUP("nullcheck", "return obj.nullcheck")); |
obj->SetAlignedPointerInInternalField(0, /* anything != nullptr */ isolate); |
ExpectInt32("nullcheck()", 5); |
obj->SetAlignedPointerInInternalField(0, nullptr); |
ExpectNull("nullcheck()"); |
// CheckFlagSetOrReturnNull: |
- CompileRun( |
- "function maskcheck() { return obj.maskcheck }; " WARMUP("maskcheck()")); |
+ CompileRun(FN_WARMUP("maskcheck", "return obj.maskcheck")); |
obj->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(0xf0)); |
ExpectInt32("maskcheck()", 42); |
obj->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(0xfe)); |
@@ -173,8 +191,6 @@ TEST(FastAccessorOrReturnNull) { |
// "Fast" accessor with simple control flow via explicit labels. |
TEST(FastAccessorControlFlowWithLabels) { |
- if (i::FLAG_always_opt) return; |
- |
LocalContext env; |
v8::Isolate* isolate = env->GetIsolate(); |
v8::HandleScope scope(isolate); |
@@ -200,7 +216,7 @@ TEST(FastAccessorControlFlowWithLabels) { |
CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust()); |
// CheckNotZeroOrReturnNull: |
- CompileRun("function isnull() { return obj.isnull }; " WARMUP("isnull()")); |
+ CompileRun(FN_WARMUP("isnull", "return obj.isnull")); |
obj->SetAlignedPointerInInternalField(0, /* anything != nullptr */ isolate); |
ExpectInt32("isnull()", 1); |
obj->SetAlignedPointerInInternalField(0, nullptr); |
@@ -210,8 +226,6 @@ TEST(FastAccessorControlFlowWithLabels) { |
// "Fast" accessor, loading things. |
TEST(FastAccessorLoad) { |
- if (i::FLAG_always_opt) return; |
- |
LocalContext env; |
v8::Isolate* isolate = env->GetIsolate(); |
v8::HandleScope scope(isolate); |
@@ -261,7 +275,7 @@ TEST(FastAccessorLoad) { |
CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust()); |
// Access val.intval: |
- CompileRun("function nonzero() { return obj.nonzero }; " WARMUP("nonzero()")); |
+ CompileRun(FN_WARMUP("nonzero", "return obj.nonzero")); |
ExpectInt32("nonzero()", 1); |
val.intval = 0; |
ExpectInt32("nonzero()", 0); |
@@ -269,6 +283,6 @@ TEST(FastAccessorLoad) { |
ExpectInt32("nonzero()", 1); |
// Access val.v8val: |
- CompileRun("function loadval() { return obj.loadval }; " WARMUP("loadval()")); |
+ CompileRun(FN_WARMUP("loadval", "return obj.loadval")); |
ExpectString("loadval()", "Hello"); |
} |