Commit d15f45d4 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Parser] Avoid on-the-fly internalization for natives_syntax.

Rework Runtime::FunctionForName to take a c-string instead of a v8::String
so that the parser can parse native syntax runtime calls without doing
on-the-fly internalization.

Also adds a c-string variant of IntrinsicIndexForName for the same reasons.

BUG=v8:5215,chromium:634953

Review-Url: https://codereview.chromium.org/2324803002
Cr-Commit-Position: refs/heads/master@{#39346}
parent 429ff47e
......@@ -532,6 +532,17 @@ int Context::IntrinsicIndexForName(Handle<String> string) {
#undef COMPARE_NAME
#define COMPARE_NAME(index, type, name) \
if (strncmp(string, #name, length) == 0) return index;
int Context::IntrinsicIndexForName(const unsigned char* unsigned_string,
int length) {
const char* string = reinterpret_cast<const char*>(unsigned_string);
NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(COMPARE_NAME);
return kNotFound;
}
#undef COMPARE_NAME
#ifdef DEBUG
......
......@@ -452,6 +452,7 @@ class Context: public FixedArray {
static int ImportedFieldIndexForName(Handle<String> name);
static int IntrinsicIndexForName(Handle<String> name);
static int IntrinsicIndexForName(const unsigned char* name, int length);
#define NATIVE_CONTEXT_FIELD_ACCESSORS(index, type, name) \
inline void set_##name(type* value); \
......
......@@ -2754,12 +2754,6 @@ void Heap::CreateInitialObjects() {
#undef SYMBOL_INIT
}
// Allocate the dictionary of intrinsic function names.
Handle<NameDictionary> intrinsic_names =
NameDictionary::New(isolate(), Runtime::kNumFunctions, TENURED);
Runtime::InitializeIntrinsicFunctionNames(isolate(), intrinsic_names);
set_intrinsic_function_names(*intrinsic_names);
Handle<NameDictionary> empty_properties_dictionary =
NameDictionary::New(isolate(), 0, TENURED);
empty_properties_dictionary->SetRequiresCopyOnCapacityChange();
......
......@@ -185,7 +185,6 @@ using v8::MemoryPressureLevel;
V(FixedArray, experimental_extra_natives_source_cache, \
ExperimentalExtraNativesSourceCache) \
/* Lists and dictionaries */ \
V(NameDictionary, intrinsic_function_names, IntrinsicFunctionNames) \
V(NameDictionary, empty_properties_dictionary, EmptyPropertiesDictionary) \
V(Object, symbol_registry, SymbolRegistry) \
V(Object, script_list, ScriptList) \
......
......@@ -246,8 +246,6 @@ void ObjectStatsCollector::CollectGlobalStatistics() {
OBJECT_TO_CODE_SUB_TYPE);
RecordHashTableHelper(nullptr, heap_->code_stubs(),
CODE_STUBS_TABLE_SUB_TYPE);
RecordHashTableHelper(nullptr, heap_->intrinsic_function_names(),
INTRINSIC_FUNCTION_NAMES_SUB_TYPE);
RecordHashTableHelper(nullptr, heap_->empty_properties_dictionary(),
EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE);
CompilationCache* compilation_cache = heap_->isolate()->compilation_cache();
......
......@@ -789,7 +789,6 @@ std::ostream& operator<<(std::ostream& os, InstanceType instance_type);
V(FAST_PROPERTIES_SUB_TYPE) \
V(FAST_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
V(HANDLER_TABLE_SUB_TYPE) \
V(INTRINSIC_FUNCTION_NAMES_SUB_TYPE) \
V(JS_COLLECTION_SUB_TYPE) \
V(JS_WEAK_COLLECTION_SUB_TYPE) \
V(LITERALS_ARRAY_SUB_TYPE) \
......
......@@ -515,12 +515,14 @@ Expression* Parser::NewV8Intrinsic(const AstRawString* name,
GetClosureScope()->ForceEagerCompilation();
}
const Runtime::Function* function = Runtime::FunctionForName(name->string());
DCHECK(name->is_one_byte());
const Runtime::Function* function =
Runtime::FunctionForName(name->raw_data(), name->length());
if (function != nullptr) {
// Check for possible name clash.
DCHECK_EQ(Context::kNotFound,
Context::IntrinsicIndexForName(name->string()));
Context::IntrinsicIndexForName(name->raw_data(), name->length()));
// Check for built-in IS_VAR macro.
if (function->function_id == Runtime::kIS_VAR) {
DCHECK_EQ(Runtime::RUNTIME, function->intrinsic_type);
......@@ -546,7 +548,8 @@ Expression* Parser::NewV8Intrinsic(const AstRawString* name,
return factory()->NewCallRuntime(function, args, pos);
}
int context_index = Context::IntrinsicIndexForName(name->string());
int context_index =
Context::IntrinsicIndexForName(name->raw_data(), name->length());
// Check that the function is defined.
if (context_index == Context::kNotFound) {
......@@ -4021,12 +4024,6 @@ bool Parser::Parse(ParseInfo* info) {
DCHECK(parsing_on_main_thread_);
Isolate* isolate = info->isolate();
pre_parse_timer_ = isolate->counters()->pre_parse();
if (FLAG_trace_parse || allow_natives() || extension_ != NULL) {
// If intrinsics are allowed, the Parser cannot operate independent of the
// V8 heap because of Runtime. Tell the string table to internalize strings
// and values right after they're created.
ast_value_factory()->Internalize(isolate);
}
if (info->is_lazy()) {
DCHECK(!info->is_eval());
......
......@@ -5,6 +5,7 @@
#include "src/runtime/runtime.h"
#include "src/assembler.h"
#include "src/base/hashmap.h"
#include "src/contexts.h"
#include "src/handles-inl.h"
#include "src/heap/heap.h"
......@@ -57,30 +58,61 @@ static const Runtime::Function kIntrinsicFunctions[] = {
#undef I
#undef F
namespace {
void Runtime::InitializeIntrinsicFunctionNames(Isolate* isolate,
Handle<NameDictionary> dict) {
DCHECK(dict->NumberOfElements() == 0);
HandleScope scope(isolate);
for (int i = 0; i < kNumFunctions; ++i) {
const char* name = kIntrinsicFunctions[i].name;
if (name == NULL) continue;
Handle<NameDictionary> new_dict = NameDictionary::Add(
dict, isolate->factory()->InternalizeUtf8String(name),
Handle<Smi>(Smi::FromInt(i), isolate), PropertyDetails::Empty());
// The dictionary does not need to grow.
CHECK(new_dict.is_identical_to(dict));
V8_DECLARE_ONCE(initialize_function_name_map_once);
static const base::HashMap* kRuntimeFunctionNameMap;
struct IntrinsicFunctionIdentifier {
IntrinsicFunctionIdentifier(const unsigned char* data, const int length)
: data_(data), length_(length) {}
static bool Match(void* key1, void* key2) {
const IntrinsicFunctionIdentifier* lhs =
static_cast<IntrinsicFunctionIdentifier*>(key1);
const IntrinsicFunctionIdentifier* rhs =
static_cast<IntrinsicFunctionIdentifier*>(key2);
if (lhs->length_ != rhs->length_) return false;
return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs->data_),
reinterpret_cast<const uint8_t*>(rhs->data_),
rhs->length_) == 0;
}
uint32_t Hash() {
return StringHasher::HashSequentialString<uint8_t>(
data_, length_, v8::internal::kZeroHashSeed);
}
}
const unsigned char* data_;
const int length_;
};
void InitializeIntrinsicFunctionNames() {
base::HashMap* function_name_map =
new base::HashMap(IntrinsicFunctionIdentifier::Match);
for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
const Runtime::Function* function = &kIntrinsicFunctions[i];
IntrinsicFunctionIdentifier* identifier = new IntrinsicFunctionIdentifier(
reinterpret_cast<const unsigned char*>(function->name),
static_cast<int>(strlen(function->name)));
base::HashMap::Entry* entry =
function_name_map->InsertNew(identifier, identifier->Hash());
entry->value = const_cast<Runtime::Function*>(function);
}
kRuntimeFunctionNameMap = function_name_map;
}
const Runtime::Function* Runtime::FunctionForName(Handle<String> name) {
Heap* heap = name->GetHeap();
int entry = heap->intrinsic_function_names()->FindEntry(name);
if (entry != kNotFound) {
Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
int function_index = Smi::cast(smi_index)->value();
return &(kIntrinsicFunctions[function_index]);
} // namespace
const Runtime::Function* Runtime::FunctionForName(const unsigned char* name,
int length) {
base::CallOnce(&initialize_function_name_map_once,
&InitializeIntrinsicFunctionNames);
IntrinsicFunctionIdentifier identifier(name, length);
base::HashMap::Entry* entry =
kRuntimeFunctionNameMap->Lookup(&identifier, identifier.Hash());
if (entry) {
return reinterpret_cast<Function*>(entry->value);
}
return NULL;
}
......
......@@ -1028,13 +1028,8 @@ class Runtime : public AllStatic {
static const int kNotFound = -1;
// Add internalized strings for all the intrinsic function names to a
// StringDictionary.
static void InitializeIntrinsicFunctionNames(Isolate* isolate,
Handle<NameDictionary> dict);
// Get the intrinsic function with the given name, which must be internalized.
static const Function* FunctionForName(Handle<String> name);
// Get the intrinsic function with the given name.
static const Function* FunctionForName(const unsigned char* name, int length);
// Get the intrinsic function with the given FunctionId.
static const Function* FunctionForId(FunctionId id);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment