OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // TODO(jochen): Remove this after the setting is turned on globally. |
| 6 #define V8_IMMINENT_DEPRECATION_WARNINGS |
| 7 |
| 8 #include <stdlib.h> |
| 9 |
| 10 #include "include/v8.h" |
| 11 |
| 12 #include "src/api.h" |
| 13 #include "test/cctest/cctest.h" |
| 14 |
| 15 namespace { |
| 16 |
| 17 // These tests mean to exercise v8::FastAccessorBuilder. Since initially the |
| 18 // "native" accessor will get called, we need to 'warmup' any accessor first, |
| 19 // to make sure we're actually testing the v8::FastAccessorBuilder result. |
| 20 // To accomplish this, we will |
| 21 // - call each accesssor N times before the actual test. |
| 22 // - wrap that call in a function, so that all such calls will go |
| 23 // through a single call site. |
| 24 // - register a native accessor which is different from the build one |
| 25 // (so that our tests will always fail if we don't end up in the 'fast' |
| 26 // accessor) |
| 27 #define WARMUP(src) "for(i = 0; i < 2; i++) { " src " } " |
| 28 |
| 29 static void NativePropertyAccessor( |
| 30 const v8::FunctionCallbackInfo<v8::Value>& info) { |
| 31 info.GetReturnValue().Set(v8_num(123)); |
| 32 } |
| 33 |
| 34 } // anonymous namespace |
| 35 |
| 36 |
| 37 // Build a simple "fast accessor" and verify that it is being called. |
| 38 TEST(FastAccessor) { |
| 39 LocalContext env; |
| 40 v8::Isolate* isolate = env->GetIsolate(); |
| 41 v8::HandleScope scope(isolate); |
| 42 |
| 43 v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate); |
| 44 |
| 45 // Native accessor, bar, returns 123. |
| 46 foo->PrototypeTemplate()->SetAccessorProperty( |
| 47 v8_str("bar"), |
| 48 v8::FunctionTemplate::New(isolate, NativePropertyAccessor)); |
| 49 |
| 50 // Fast accessor, barf, returns 124. |
| 51 auto fab = v8::experimental::FastAccessorBuilder::New(isolate); |
| 52 fab->ReturnValue(fab->IntegerConstant(124)); |
| 53 foo->PrototypeTemplate()->SetAccessorProperty( |
| 54 v8_str("barf"), v8::FunctionTemplate::NewWithFastHandler( |
| 55 isolate, NativePropertyAccessor, fab)); |
| 56 |
| 57 // Install foo on the global object. |
| 58 CHECK(env->Global() |
| 59 ->Set(env.local(), v8_str("foo"), |
| 60 foo->GetFunction(env.local()).ToLocalChecked()) |
| 61 .FromJust()); |
| 62 |
| 63 // Wrap f.barf + IC warmup. |
| 64 CompileRun( |
| 65 "function barf() { f = new foo(); return f.barf }; " WARMUP("barf()")); |
| 66 |
| 67 ExpectInt32("f = new foo(); f.bar", 123); |
| 68 ExpectInt32("f = new foo(); f.barf", 123); // First call in this call site. |
| 69 ExpectInt32("barf()", 124); // Call via warmed-up callsite. |
| 70 } |
| 71 |
| 72 |
| 73 void AddInternalFieldAccessor(v8::Isolate* isolate, |
| 74 v8::Local<v8::Template> templ, const char* name, |
| 75 int field_no) { |
| 76 auto builder = v8::experimental::FastAccessorBuilder::New(isolate); |
| 77 builder->ReturnValue( |
| 78 builder->GetInternalField(builder->GetCallTarget(), field_no)); |
| 79 templ->SetAccessorProperty(v8_str(name), |
| 80 v8::FunctionTemplate::NewWithFastHandler( |
| 81 isolate, NativePropertyAccessor, builder)); |
| 82 } |
| 83 |
| 84 |
| 85 // "Fast" accessor that accesses an internal field. |
| 86 TEST(FastAccessorWithInternalField) { |
| 87 LocalContext env; |
| 88 v8::Isolate* isolate = env->GetIsolate(); |
| 89 v8::HandleScope scope(isolate); |
| 90 |
| 91 v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate); |
| 92 foo->SetInternalFieldCount(3); |
| 93 AddInternalFieldAccessor(isolate, foo, "field0", 0); |
| 94 AddInternalFieldAccessor(isolate, foo, "field1", 1); |
| 95 AddInternalFieldAccessor(isolate, foo, "field2", 2); |
| 96 |
| 97 // Create an instance w/ 3 internal fields, put in a string, a Smi, nothing. |
| 98 v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked(); |
| 99 obj->SetInternalField(0, v8_str("Hi there!")); |
| 100 obj->SetInternalField(1, v8::Integer::New(isolate, 4321)); |
| 101 CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust()); |
| 102 |
| 103 // Warmup. |
| 104 CompileRun("function field0() { return obj.field0 }; " WARMUP("field0()")); |
| 105 CompileRun("function field1() { return obj.field1 }; " WARMUP("field1()")); |
| 106 CompileRun("function field2() { return obj.field2 }; " WARMUP("field2()")); |
| 107 |
| 108 // Access fields. |
| 109 ExpectString("field0()", "Hi there!"); |
| 110 ExpectInt32("field1()", 4321); |
| 111 ExpectUndefined("field2()"); |
| 112 } |
OLD | NEW |