From 6ae42d9171f563374091f14e0b4d21e4a2f508ac Mon Sep 17 00:00:00 2001 From: "dslomov@chromium.org" Date: Mon, 20 Oct 2014 13:33:34 +0000 Subject: [PATCH] Simplify language feature management. R=rossberg@chromium.org BUG=v8:3640 LOG=N Review URL: https://codereview.chromium.org/642233003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24743 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/bootstrapper.cc | 144 ++++++++++++++++++++++++++++++++++++------- src/flag-definitions.h | 69 +++++++++++++-------- src/runtime/runtime-test.cc | 7 +++ src/runtime/runtime.h | 1 + test/mjsunit/debug-script.js | 3 +- 5 files changed, 174 insertions(+), 50 deletions(-) diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index eafc89b..029dc52 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -128,7 +128,7 @@ char* Bootstrapper::AllocateAutoDeletedArray(int bytes) { void Bootstrapper::TearDown() { if (delete_these_non_arrays_on_tear_down_ != NULL) { int len = delete_these_non_arrays_on_tear_down_->length(); - DCHECK(len < 28); // Don't use this mechanism for unbounded allocations. + DCHECK(len < 1000); // Don't use this mechanism for unbounded allocations. for (int i = 0; i < len; i++) { delete delete_these_non_arrays_on_tear_down_->at(i); delete_these_non_arrays_on_tear_down_->at(i) = NULL; @@ -210,6 +210,18 @@ class Genesis BASE_EMBEDDED { // Used for creating a context from scratch. void InstallNativeFunctions(); void InstallExperimentalNativeFunctions(); + +#define DECLARE_FEATURE_INITIALIZATION(id, descr) \ + void InstallNativeFunctions_##id(); \ + void InitializeGlobal_##id(); + + SHIPPING_FEATURES(DECLARE_FEATURE_INITIALIZATION) + HARMONY_FEATURES(DECLARE_FEATURE_INITIALIZATION) + STAGED_FEATURES(DECLARE_FEATURE_INITIALIZATION) + + DECLARE_FEATURE_INITIALIZATION(harmony_proxies, "") +#undef DECLARE_FEATURE_INITIALIZATION + Handle InstallInternalArray(Handle builtins, const char* name, ElementsKind elements_kind); @@ -1330,6 +1342,11 @@ void Genesis::InitializeGlobal(Handle global_object, delegate->shared()->DontAdaptArguments(); } +#define FEATURE_INITIALIZE_GLOBAL(id, descr) InitializeGlobal_##id(); + + SHIPPING_FEATURES(FEATURE_INITIALIZE_GLOBAL) +#undef FEATURE_INITIALIZE_GLOBAL + // Initialize the embedder data slot. Handle embedder_data = factory->NewFixedArray(3); native_context()->set_embedder_data(*embedder_data); @@ -1360,16 +1377,11 @@ void Genesis::InstallTypedArray( void Genesis::InitializeExperimentalGlobal() { - // TODO(erikcorry): Move this into Genesis::InitializeGlobal once we no - // longer need to live behind a flag. - Handle builtins(native_context()->builtins()); +#define FEATURE_INITIALIZE_GLOBAL(id, descr) InitializeGlobal_##id(); - Handle flag( - FLAG_harmony_regexps ? heap()->true_value() : heap()->false_value()); - PropertyAttributes attributes = - static_cast(DONT_DELETE | READ_ONLY); - Runtime::DefineObjectProperty(builtins, factory()->harmony_regexps_string(), - flag, attributes).Assert(); + HARMONY_FEATURES(FEATURE_INITIALIZE_GLOBAL) + STAGED_FEATURES(FEATURE_INITIALIZE_GLOBAL) +#undef FEATURE_INITIALIZE_GLOBAL } @@ -1551,6 +1563,11 @@ void Genesis::InstallNativeFunctions() { INSTALL_NATIVE(Symbol, "symbolIterator", iterator_symbol); INSTALL_NATIVE(Symbol, "symbolUnscopables", unscopables_symbol); INSTALL_NATIVE(JSFunction, "ArrayValues", array_values_iterator); + +#define INSTALL_NATIVE_FUNCTIONS_FOR(id, descr) InstallNativeFunctions_##id(); + + SHIPPING_FEATURES(INSTALL_NATIVE_FUNCTIONS_FOR) +#undef INSTALL_NATIVE_FUNCTIONS_FOR } @@ -1561,10 +1578,64 @@ void Genesis::InstallExperimentalNativeFunctions() { INSTALL_NATIVE(JSFunction, "DerivedSetTrap", derived_set_trap); INSTALL_NATIVE(JSFunction, "ProxyEnumerate", proxy_enumerate); } + +#define INSTALL_NATIVE_FUNCTIONS_FOR(id, descr) InstallNativeFunctions_##id(); + + HARMONY_FEATURES(INSTALL_NATIVE_FUNCTIONS_FOR) + STAGED_FEATURES(INSTALL_NATIVE_FUNCTIONS_FOR) + INSTALL_NATIVE_FUNCTIONS_FOR(harmony_proxies, "") +#undef INSTALL_NATIVE_FUNCTIONS_FOR +} + + +#define EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(id) \ + void Genesis::InstallNativeFunctions_##id() {} + +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_scoping) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_modules) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_strings) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_arrays) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_classes) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_object_literals) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_regexps) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_arrow_functions) +EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_numeric_literals) + + +void Genesis::InstallNativeFunctions_harmony_proxies() { + if (FLAG_harmony_proxies) { + INSTALL_NATIVE(JSFunction, "DerivedHasTrap", derived_has_trap); + INSTALL_NATIVE(JSFunction, "DerivedGetTrap", derived_get_trap); + INSTALL_NATIVE(JSFunction, "DerivedSetTrap", derived_set_trap); + INSTALL_NATIVE(JSFunction, "ProxyEnumerate", proxy_enumerate); + } } #undef INSTALL_NATIVE +#define EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(id) \ + void Genesis::InitializeGlobal_##id() {} + +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_scoping) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_modules) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_strings) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_arrays) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_classes) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_object_literals) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_arrow_functions) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_numeric_literals) + +void Genesis::InitializeGlobal_harmony_regexps() { + Handle builtins(native_context()->builtins()); + + Handle flag(FLAG_harmony_regexps ? heap()->true_value() + : heap()->false_value()); + PropertyAttributes attributes = + static_cast(DONT_DELETE | READ_ONLY); + Runtime::DefineObjectProperty(builtins, factory()->harmony_regexps_string(), + flag, attributes).Assert(); +} + Handle Genesis::InstallInternalArray( Handle builtins, @@ -2071,24 +2142,51 @@ bool Genesis::InstallNatives() { } -#define INSTALL_EXPERIMENTAL_NATIVE(i, flag, file) \ - if (FLAG_harmony_##flag && \ - strcmp(ExperimentalNatives::GetScriptName(i).start(), \ - "native " file) == 0) { \ - if (!CompileExperimentalBuiltin(isolate(), i)) return false; \ +#define INSTALL_EXPERIMENTAL_NATIVE(i, flag, file) \ + if (FLAG_##flag && \ + strcmp(ExperimentalNatives::GetScriptName(i).start(), "native " file) == \ + 0) { \ + if (!CompileExperimentalBuiltin(isolate(), i)) return false; \ } bool Genesis::InstallExperimentalNatives() { + static const char* harmony_arrays_natives[] = { + "native harmony-array.js", "native harmony-typedarray.js", NULL}; + static const char* harmony_proxies_natives[] = {"native proxy.js", NULL}; + static const char* harmony_strings_natives[] = {"native harmony-string.js", + NULL}; + static const char* harmony_classes_natives[] = {"native harmony-classes.js", + NULL}; + static const char* harmony_modules_natives[] = {NULL}; + static const char* harmony_scoping_natives[] = {NULL}; + static const char* harmony_object_literals_natives[] = {NULL}; + static const char* harmony_regexps_natives[] = {NULL}; + static const char* harmony_arrow_functions_natives[] = {NULL}; + static const char* harmony_numeric_literals_natives[] = {NULL}; + for (int i = ExperimentalNatives::GetDebuggerCount(); - i < ExperimentalNatives::GetBuiltinsCount(); - i++) { - INSTALL_EXPERIMENTAL_NATIVE(i, proxies, "proxy.js") - INSTALL_EXPERIMENTAL_NATIVE(i, strings, "harmony-string.js") - INSTALL_EXPERIMENTAL_NATIVE(i, arrays, "harmony-array.js") - INSTALL_EXPERIMENTAL_NATIVE(i, arrays, "harmony-typedarray.js") - INSTALL_EXPERIMENTAL_NATIVE(i, classes, "harmony-classes.js") - } + i < ExperimentalNatives::GetBuiltinsCount(); i++) { +#define INSTALL_EXPERIMENTAL_NATIVES(id, desc) \ + if (FLAG_##id) { \ + for (size_t j = 0; id##_natives[j] != NULL; j++) { \ + if (strcmp(ExperimentalNatives::GetScriptName(i).start(), \ + id##_natives[j]) == 0) { \ + if (!CompileExperimentalBuiltin(isolate(), i)) return false; \ + } \ + } \ + } + INSTALL_EXPERIMENTAL_NATIVES(harmony_proxies, ""); + // Iterate over flags that are not enabled by default. + HARMONY_FEATURES(INSTALL_EXPERIMENTAL_NATIVES); + STAGED_FEATURES(INSTALL_EXPERIMENTAL_NATIVES); +#undef INSTALL_EXPERIMENTAL_NATIVES + } + +#define USE_NATIVES_FOR_FEATURE(id, descr) USE(id##_natives); + + SHIPPING_FEATURES(USE_NATIVES_FOR_FEATURE) +#undef USE_NATIVES_FOR_FEATURE InstallExperimentalNativeFunctions(); return true; diff --git a/src/flag-definitions.h b/src/flag-definitions.h index c2abd0f..4707635 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -126,6 +126,8 @@ struct MaybeBoolFlag { #endif #define DEFINE_BOOL(nam, def, cmt) FLAG(BOOL, bool, nam, def, cmt) +#define DEFINE_BOOL_READONLY(nam, def, cmt) \ + FLAG_READONLY(BOOL, bool, nam, def, cmt) #define DEFINE_MAYBE_BOOL(nam, cmt) \ FLAG(MAYBE_BOOL, MaybeBoolFlag, nam, {false COMMA false}, cmt) #define DEFINE_INT(nam, def, cmt) FLAG(INT, int, nam, def, cmt) @@ -147,39 +149,54 @@ struct MaybeBoolFlag { // Flags for language modes and experimental language features. DEFINE_BOOL(use_strict, false, "enforce strict mode") -DEFINE_BOOL(es_staging, false, "enable upcoming ES6+ features") -DEFINE_BOOL(harmony_scoping, false, "enable harmony block scoping") -DEFINE_BOOL(harmony_modules, false, - "enable harmony modules (implies block scoping)") -DEFINE_BOOL(harmony_proxies, false, "enable harmony proxies") -DEFINE_BOOL(harmony_numeric_literals, false, - "enable harmony numeric literals (0o77, 0b11)") -DEFINE_BOOL(harmony_strings, false, "enable harmony string") -DEFINE_BOOL(harmony_arrays, false, "enable harmony arrays") -DEFINE_BOOL(harmony_arrow_functions, false, "enable harmony arrow functions") -DEFINE_BOOL(harmony_classes, false, "enable harmony classes") -DEFINE_BOOL(harmony_object_literals, false, - "enable harmony object literal extensions") -DEFINE_BOOL(harmony_regexps, false, "enable regexp-related harmony features") +DEFINE_BOOL(es_staging, false, "enable upcoming ES6+ features") DEFINE_BOOL(harmony, false, "enable all harmony features (except proxies)") +DEFINE_IMPLICATION(harmony, es_staging) -DEFINE_IMPLICATION(harmony, harmony_scoping) -DEFINE_IMPLICATION(harmony, harmony_modules) -// TODO(rossberg): Reenable when problems are sorted out. -// DEFINE_IMPLICATION(harmony, harmony_proxies) -DEFINE_IMPLICATION(harmony, harmony_strings) -DEFINE_IMPLICATION(harmony, harmony_arrays) -DEFINE_IMPLICATION(harmony, harmony_arrow_functions) -DEFINE_IMPLICATION(harmony, harmony_classes) -DEFINE_IMPLICATION(harmony, harmony_object_literals) -DEFINE_IMPLICATION(harmony, harmony_regexps) +#define HARMONY_FEATURES(V) \ + V(harmony_scoping, "harmony block scoping") \ + V(harmony_modules, "harmony modules (implies block scoping)") \ + V(harmony_strings, "harmony strings") \ + V(harmony_arrays, "harmony arrays") \ + V(harmony_classes, "harmony classes") \ + V(harmony_object_literals, "harmony object literal extensions") \ + V(harmony_regexps, "reg-exp related harmony features") \ + V(harmony_arrow_functions, "harmony arrow functions") + +#define STAGED_FEATURES(V) \ + V(harmony_numeric_literals, "harmony numeric literals (0o77, 0b11)") + +#define SHIPPING_FEATURES(V) + +#define FLAG_FEATURES(id, description) \ + DEFINE_BOOL(id, false, "enable " #description) \ + DEFINE_IMPLICATION(harmony, id) + +HARMONY_FEATURES(FLAG_FEATURES) +STAGED_FEATURES(FLAG_FEATURES) +#undef FLAG_FEATURES + +#define FLAG_STAGED_FEATURES(id, description) DEFINE_IMPLICATION(es_staging, id) + +STAGED_FEATURES(FLAG_STAGED_FEATURES) +#undef FLAG_STAGED_FEATURES + +#define FLAG_SHIPPING_FEATURES(id, description) \ + DEFINE_BOOL_READONLY(id, true, "enable " #description) + +SHIPPING_FEATURES(FLAG_SHIPPING_FEATURES) +#undef FLAG_SHIPPING_FEATURES + +// Feature dependencies. DEFINE_IMPLICATION(harmony_modules, harmony_scoping) DEFINE_IMPLICATION(harmony_classes, harmony_scoping) DEFINE_IMPLICATION(harmony_classes, harmony_object_literals) -DEFINE_IMPLICATION(harmony, es_staging) -DEFINE_IMPLICATION(es_staging, harmony_numeric_literals) +DEFINE_BOOL(harmony_proxies, false, "enable harmony proxies") +// TODO(rossberg): Reenable when problems are sorted out. +// DEFINE_IMPLICATION(harmony, harmony_proxies) + // Flags for experimental implementation features. DEFINE_BOOL(compiled_keyed_generic_loads, false, diff --git a/src/runtime/runtime-test.cc b/src/runtime/runtime-test.cc index cf0a239..6b3fd13 100644 --- a/src/runtime/runtime-test.cc +++ b/src/runtime/runtime-test.cc @@ -7,6 +7,7 @@ #include "src/arguments.h" #include "src/deoptimizer.h" #include "src/full-codegen.h" +#include "src/natives.h" #include "src/runtime/runtime-utils.h" namespace v8 { @@ -293,6 +294,12 @@ RUNTIME_FUNCTION(Runtime_AbortJS) { } +RUNTIME_FUNCTION(Runtime_NativeScriptsCount) { + DCHECK(args.length() == 0); + return Smi::FromInt(Natives::GetBuiltinsCount()); +} + + // Returns V8 version as a string. RUNTIME_FUNCTION(Runtime_GetV8Version) { HandleScope scope(isolate); diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 350fd92..36c0fc9 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -390,6 +390,7 @@ namespace internal { F(TraceExit, 1, 1) \ F(Abort, 1, 1) \ F(AbortJS, 1, 1) \ + F(NativeScriptsCount, 0, 1) \ /* ES5 */ \ F(OwnKeys, 1, 1) \ \ diff --git a/test/mjsunit/debug-script.js b/test/mjsunit/debug-script.js index 5ffada1..44102c2 100644 --- a/test/mjsunit/debug-script.js +++ b/test/mjsunit/debug-script.js @@ -26,6 +26,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug --expose-gc --send-idle-notification +// Flags: --allow-natives-syntax // Get the Debug object exposed from the debug context global object. Debug = debug.Debug; @@ -59,7 +60,7 @@ for (i = 0; i < scripts.length; i++) { } // This has to be updated if the number of native scripts change. -assertTrue(named_native_count == 26 || named_native_count == 27); +assertEquals(%NativeScriptsCount(), named_native_count); // Only the 'gc' extension is loaded. assertEquals(1, extension_count); // This script and mjsunit.js has been loaded. If using d8, d8 loads -- 2.7.4