Avoid static initializers in PropertyAccessCompiler

Introduce AccessCompilerData which hangs off the Isolate, and initialize
it when the first PropertyAccessCompiler is instantiated. This avoids
TSAN failures when trying to access load/store calling convention arrays.

BUG=v8:5427

Review-Url: https://codereview.chromium.org/2389313002
Cr-Commit-Position: refs/heads/master@{#40055}
This commit is contained in:
adamk 2016-10-06 11:19:44 -07:00 committed by Commit bot
parent 4b575dfcef
commit b5c542bac8
16 changed files with 166 additions and 119 deletions

View File

@ -1378,6 +1378,7 @@ v8_source_set("v8_base") {
"src/heap/store-buffer.h",
"src/i18n.cc",
"src/i18n.h",
"src/ic/access-compiler-data.h",
"src/ic/access-compiler.cc",
"src/ic/access-compiler.h",
"src/ic/call-optimization.cc",

View File

@ -0,0 +1,48 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_IC_ACCESS_COMPILER_DATA_H_
#define V8_IC_ACCESS_COMPILER_DATA_H_
#include <memory>
#include "src/allocation.h"
#include "src/base/macros.h"
namespace v8 {
namespace internal {
class AccessCompilerData {
public:
AccessCompilerData() {}
bool IsInitialized() const { return load_calling_convention_ != nullptr; }
void Initialize(int load_register_count, const Register* load_registers,
int store_register_count, const Register* store_registers) {
load_calling_convention_.reset(NewArray<Register>(load_register_count));
for (int i = 0; i < load_register_count; ++i) {
load_calling_convention_[i] = load_registers[i];
}
store_calling_convention_.reset(NewArray<Register>(store_register_count));
for (int i = 0; i < store_register_count; ++i) {
store_calling_convention_[i] = store_registers[i];
}
}
Register* load_calling_convention() { return load_calling_convention_.get(); }
Register* store_calling_convention() {
return store_calling_convention_.get();
}
private:
std::unique_ptr<Register[]> load_calling_convention_;
std::unique_ptr<Register[]> store_calling_convention_;
DISALLOW_COPY_AND_ASSIGN(AccessCompilerData);
};
} // namespace internal
} // namespace v8
#endif // V8_IC_ACCESS_COMPILER_DATA_H_

View File

@ -4,7 +4,6 @@
#include "src/ic/access-compiler.h"
namespace v8 {
namespace internal {
@ -42,13 +41,17 @@ void PropertyAccessCompiler::TailCallBuiltin(MacroAssembler* masm,
GenerateTailCall(masm, code);
}
Register* PropertyAccessCompiler::GetCallingConvention(Code::Kind kind) {
Register* PropertyAccessCompiler::GetCallingConvention(Isolate* isolate,
Code::Kind kind) {
AccessCompilerData* data = isolate->access_compiler_data();
if (!data->IsInitialized()) {
InitializePlatformSpecific(data);
}
if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC) {
return load_calling_convention();
return data->load_calling_convention();
}
DCHECK(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
return store_calling_convention();
return data->store_calling_convention();
}

View File

@ -6,13 +6,13 @@
#define V8_IC_ACCESS_COMPILER_H_
#include "src/code-stubs.h"
#include "src/ic/access-compiler-data.h"
#include "src/macro-assembler.h"
#include "src/objects.h"
namespace v8 {
namespace internal {
class PropertyAccessCompiler BASE_EMBEDDED {
public:
static Builtins::Name MissBuiltin(Code::Kind kind) {
@ -36,7 +36,7 @@ class PropertyAccessCompiler BASE_EMBEDDED {
protected:
PropertyAccessCompiler(Isolate* isolate, Code::Kind kind,
CacheHolderFlag cache_holder)
: registers_(GetCallingConvention(kind)),
: registers_(GetCallingConvention(isolate, kind)),
kind_(kind),
cache_holder_(cache_holder),
isolate_(isolate),
@ -59,11 +59,6 @@ class PropertyAccessCompiler BASE_EMBEDDED {
Register scratch1() const { return registers_[2]; }
Register scratch2() const { return registers_[3]; }
static Register* GetCallingConvention(Code::Kind);
static Register* load_calling_convention();
static Register* store_calling_convention();
static Register* keyed_store_calling_convention();
Register* registers_;
static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code);
@ -72,6 +67,9 @@ class PropertyAccessCompiler BASE_EMBEDDED {
Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<Name> name);
private:
static Register* GetCallingConvention(Isolate* isolate, Code::Kind kind);
static void InitializePlatformSpecific(AccessCompilerData* data);
Code::Kind kind_;
CacheHolderFlag cache_holder_;

View File

@ -17,24 +17,22 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
__ Jump(code, RelocInfo::CODE_TARGET);
}
Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3.
void PropertyAccessCompiler::InitializePlatformSpecific(
AccessCompilerData* data) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
static Register registers[] = {receiver, name, r3, r0, r4};
return registers;
}
// Load calling convention.
// receiver, name, scratch1, scratch2, scratch3.
Register load_registers[] = {receiver, name, r3, r0, r4};
Register* PropertyAccessCompiler::store_calling_convention() {
// Store calling convention.
// receiver, name, scratch1, scratch2.
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
static Register registers[] = {receiver, name, r3, r4};
return registers;
}
Register store_registers[] = {receiver, name, r3, r4};
data->Initialize(arraysize(load_registers), load_registers,
arraysize(store_registers), store_registers);
}
#undef __
} // namespace internal

View File

@ -25,24 +25,23 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
// registers are actually scratch registers, and which are important. For now,
// we use the same assignments as ARM to remain on the safe side.
Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3.
void PropertyAccessCompiler::InitializePlatformSpecific(
AccessCompilerData* data) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
static Register registers[] = {receiver, name, x3, x0, x4};
return registers;
// Load calling convention.
// receiver, name, scratch1, scratch2, scratch3.
Register load_registers[] = {receiver, name, x3, x0, x4};
// Store calling convention.
// receiver, name, scratch1, scratch2.
Register store_registers[] = {receiver, name, x3, x4};
data->Initialize(arraysize(load_registers), load_registers,
arraysize(store_registers), store_registers);
}
Register* PropertyAccessCompiler::store_calling_convention() {
// receiver, value, scratch1, scratch2.
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
static Register registers[] = {receiver, name, x3, x4};
return registers;
}
#undef __
} // namespace internal
} // namespace v8

View File

@ -16,22 +16,21 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
__ jmp(code, RelocInfo::CODE_TARGET);
}
Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3.
void PropertyAccessCompiler::InitializePlatformSpecific(
AccessCompilerData* data) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
static Register registers[] = {receiver, name, ebx, eax, edi};
return registers;
}
// Load calling convention.
// receiver, name, scratch1, scratch2, scratch3.
Register load_registers[] = {receiver, name, ebx, eax, edi};
Register* PropertyAccessCompiler::store_calling_convention() {
// Store calling convention.
// receiver, name, scratch1, scratch2.
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
static Register registers[] = {receiver, name, ebx, edi};
return registers;
Register store_registers[] = {receiver, name, ebx, edi};
data->Initialize(arraysize(load_registers), load_registers,
arraysize(store_registers), store_registers);
}
#undef __

View File

@ -17,24 +17,22 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
__ Jump(code, RelocInfo::CODE_TARGET);
}
Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3.
void PropertyAccessCompiler::InitializePlatformSpecific(
AccessCompilerData* data) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
static Register registers[] = {receiver, name, a3, a0, t0};
return registers;
}
// Load calling convention.
// receiver, name, scratch1, scratch2, scratch3.
Register load_registers[] = {receiver, name, a3, a0, t0};
Register* PropertyAccessCompiler::store_calling_convention() {
// Store calling convention.
// receiver, name, scratch1, scratch2.
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
static Register registers[] = {receiver, name, a3, t0};
return registers;
}
Register store_registers[] = {receiver, name, a3, t0};
data->Initialize(arraysize(load_registers), load_registers,
arraysize(store_registers), store_registers);
}
#undef __
} // namespace internal

View File

@ -17,24 +17,22 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
__ Jump(code, RelocInfo::CODE_TARGET);
}
Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3.
void PropertyAccessCompiler::InitializePlatformSpecific(
AccessCompilerData* data) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
static Register registers[] = {receiver, name, a3, a0, a4};
return registers;
}
// Load calling convention.
// receiver, name, scratch1, scratch2, scratch3.
Register load_registers[] = {receiver, name, a3, a0, a4};
Register* PropertyAccessCompiler::store_calling_convention() {
// Store calling convention.
// receiver, name, scratch1, scratch2.
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
static Register registers[] = {receiver, name, a3, a4};
return registers;
}
Register store_registers[] = {receiver, name, a3, a4};
data->Initialize(arraysize(load_registers), load_registers,
arraysize(store_registers), store_registers);
}
#undef __
} // namespace internal

View File

@ -17,24 +17,22 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
__ Jump(code, RelocInfo::CODE_TARGET);
}
Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3.
void PropertyAccessCompiler::InitializePlatformSpecific(
AccessCompilerData* data) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
static Register registers[] = {receiver, name, r6, r3, r7};
return registers;
}
// Load calling convention.
// receiver, name, scratch1, scratch2, scratch3.
Register load_registers[] = {receiver, name, r6, r3, r7};
Register* PropertyAccessCompiler::store_calling_convention() {
// Store calling convention.
// receiver, name, scratch1, scratch2.
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
static Register registers[] = {receiver, name, r6, r7};
return registers;
}
Register store_registers[] = {receiver, name, r6, r7};
data->Initialize(arraysize(load_registers), load_registers,
arraysize(store_registers), store_registers);
}
#undef __
} // namespace internal

View File

@ -18,20 +18,21 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
__ Jump(code, RelocInfo::CODE_TARGET);
}
Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3.
void PropertyAccessCompiler::InitializePlatformSpecific(
AccessCompilerData* data) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
static Register registers[] = {receiver, name, r5, r2, r6};
return registers;
}
Register* PropertyAccessCompiler::store_calling_convention() {
// Load calling convention.
// receiver, name, scratch1, scratch2, scratch3.
Register load_registers[] = {receiver, name, r5, r2, r6};
// Store calling convention.
// receiver, name, scratch1, scratch2.
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
static Register registers[] = {receiver, name, r5, r6};
return registers;
Register store_registers[] = {receiver, name, r5, r6};
data->Initialize(arraysize(load_registers), load_registers,
arraysize(store_registers), store_registers);
}
#undef __

View File

@ -11,30 +11,27 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
Handle<Code> code) {
__ jmp(code, RelocInfo::CODE_TARGET);
}
Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3.
void PropertyAccessCompiler::InitializePlatformSpecific(
AccessCompilerData* data) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
static Register registers[] = {receiver, name, rax, rbx, rdi};
return registers;
}
// Load calling convention.
// receiver, name, scratch1, scratch2, scratch3.
Register load_registers[] = {receiver, name, rax, rbx, rdi};
Register* PropertyAccessCompiler::store_calling_convention() {
// Store calling convention.
// receiver, name, scratch1, scratch2.
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
static Register registers[] = {receiver, name, rbx, rdi};
return registers;
}
Register store_registers[] = {receiver, name, rbx, rdi};
data->Initialize(arraysize(load_registers), load_registers,
arraysize(store_registers), store_registers);
}
#undef __
} // namespace internal

View File

@ -16,22 +16,21 @@ void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
__ jmp(code, RelocInfo::CODE_TARGET);
}
Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3.
void PropertyAccessCompiler::InitializePlatformSpecific(
AccessCompilerData* data) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
static Register registers[] = {receiver, name, ebx, eax, edi};
return registers;
}
// Load calling convention.
// receiver, name, scratch1, scratch2, scratch3.
Register load_registers[] = {receiver, name, ebx, eax, edi};
Register* PropertyAccessCompiler::store_calling_convention() {
// Store calling convention.
// receiver, name, scratch1, scratch2.
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
static Register registers[] = {receiver, name, ebx, edi};
return registers;
Register store_registers[] = {receiver, name, ebx, edi};
data->Initialize(arraysize(load_registers), load_registers,
arraysize(store_registers), store_registers);
}
#undef __

View File

@ -26,6 +26,7 @@
#include "src/deoptimizer.h"
#include "src/external-reference-table.h"
#include "src/frames-inl.h"
#include "src/ic/access-compiler-data.h"
#include "src/ic/stub-cache.h"
#include "src/interface-descriptors.h"
#include "src/interpreter/interpreter.h"
@ -2211,6 +2212,9 @@ Isolate::~Isolate() {
delete[] call_descriptor_data_;
call_descriptor_data_ = NULL;
delete access_compiler_data_;
access_compiler_data_ = NULL;
delete regexp_stack_;
regexp_stack_ = NULL;
@ -2378,6 +2382,7 @@ bool Isolate::Init(Deserializer* des) {
date_cache_ = new DateCache();
call_descriptor_data_ =
new CallInterfaceDescriptorData[CallDescriptors::NUMBER_OF_DESCRIPTORS];
access_compiler_data_ = new AccessCompilerData();
cpu_profiler_ = new CpuProfiler(this);
heap_profiler_ = new HeapProfiler(heap());
interpreter_ = new interpreter::Interpreter(this);

View File

@ -33,6 +33,7 @@ class RandomNumberGenerator;
namespace internal {
class AccessCompilerData;
class BasicBlockProfiler;
class Bootstrapper;
class CancelableTaskManager;
@ -1029,6 +1030,8 @@ class Isolate {
CallInterfaceDescriptorData* call_descriptor_data(int index);
AccessCompilerData* access_compiler_data() { return access_compiler_data_; }
void IterateDeferredHandles(ObjectVisitor* visitor);
void LinkDeferredHandles(DeferredHandles* deferred_handles);
void UnlinkDeferredHandles(DeferredHandles* deferred_handles);
@ -1342,6 +1345,7 @@ class Isolate {
List<int> regexp_indices_;
DateCache* date_cache_;
CallInterfaceDescriptorData* call_descriptor_data_;
AccessCompilerData* access_compiler_data_;
base::RandomNumberGenerator* random_number_generator_;
base::AtomicValue<RAILMode> rail_mode_;

View File

@ -950,6 +950,7 @@
'i18n.h',
'icu_util.cc',
'icu_util.h',
'ic/access-compiler-data.h',
'ic/access-compiler.cc',
'ic/access-compiler.h',
'ic/call-optimization.cc',