Commit 23ac686f authored by bmeurer's avatar bmeurer Committed by Commit bot

[types] Use the TypeCache consistently for common types.

Rename ZoneTypeCache to TypeCache and use a single shared (immutable)
instance consistently to cache the most commonly used types. Also serves
as a chokepoint for defining those types, so we don't repeat the
definition (and possible bugs) in various places.

R=jarin@chromium.org

Review URL: https://codereview.chromium.org/1409763004

Cr-Commit-Position: refs/heads/master@{#31631}
parent 4a2bb890
......@@ -1241,6 +1241,8 @@ source_set("v8_base") {
"src/transitions-inl.h",
"src/transitions.cc",
"src/transitions.h",
"src/type-cache.cc",
"src/type-cache.h",
"src/type-feedback-vector-inl.h",
"src/type-feedback-vector.cc",
"src/type-feedback-vector.h",
......@@ -1273,7 +1275,6 @@ source_set("v8_base") {
"src/version.h",
"src/vm-state-inl.h",
"src/vm-state.h",
"src/zone-type-cache.h",
"src/zone.cc",
"src/zone.h",
"src/zone-allocator.h",
......
......@@ -3,6 +3,11 @@
// found in the LICENSE file.
#include "src/compiler/access-builder.h"
#include "src/contexts.h"
#include "src/frames.h"
#include "src/heap/heap.h"
#include "src/type-cache.h"
#include "src/types-inl.h"
namespace v8 {
......@@ -20,7 +25,7 @@ FieldAccess AccessBuilder::ForMap() {
// static
FieldAccess AccessBuilder::ForJSObjectProperties() {
FieldAccess access = {kTaggedBase, JSObject::kPropertiesOffset,
MaybeHandle<Name>(), Type::Any(), kMachAnyTagged};
MaybeHandle<Name>(), Type::Internal(), kMachAnyTagged};
return access;
}
......@@ -67,12 +72,10 @@ FieldAccess AccessBuilder::ForJSDateField(JSDate::FieldIndex index) {
// static
FieldAccess AccessBuilder::ForFixedArrayLength(Zone* zone) {
FieldAccess access = {
kTaggedBase, FixedArray::kLengthOffset, MaybeHandle<Name>(),
Type::Intersect(Type::Range(0, FixedArray::kMaxLength, zone),
Type::TaggedSigned(), zone),
kMachAnyTagged};
FieldAccess AccessBuilder::ForFixedArrayLength() {
FieldAccess access = {kTaggedBase, FixedArray::kLengthOffset,
MaybeHandle<Name>(),
TypeCache::Get().kFixedArrayLengthType, kMachAnyTagged};
return access;
}
......@@ -95,11 +98,9 @@ FieldAccess AccessBuilder::ForDescriptorArrayEnumCacheBridgeCache() {
// static
FieldAccess AccessBuilder::ForMapBitField3(Zone* zone) {
FieldAccess access = {
kTaggedBase, Map::kBitField3Offset, Handle<Name>(),
Type::Intersect(Type::Signed32(), Type::UntaggedSigned32(), zone),
kMachInt32};
FieldAccess AccessBuilder::ForMapBitField3() {
FieldAccess access = {kTaggedBase, Map::kBitField3Offset, Handle<Name>(),
TypeCache::Get().kInt32, kMachInt32};
return access;
}
......@@ -115,18 +116,15 @@ FieldAccess AccessBuilder::ForMapDescriptors() {
// static
FieldAccess AccessBuilder::ForMapInstanceType() {
FieldAccess access = {kTaggedBase, Map::kInstanceTypeOffset, Handle<Name>(),
Type::UntaggedUnsigned8(), kMachUint8};
TypeCache::Get().kUint8, kMachUint8};
return access;
}
// static
FieldAccess AccessBuilder::ForStringLength(Zone* zone) {
FieldAccess access = {
kTaggedBase, String::kLengthOffset, Handle<Name>(),
Type::Intersect(Type::Range(0, String::kMaxLength, zone),
Type::TaggedSigned(), zone),
kMachAnyTagged};
FieldAccess AccessBuilder::ForStringLength() {
FieldAccess access = {kTaggedBase, String::kLengthOffset, Handle<Name>(),
TypeCache::Get().kStringLengthType, kMachAnyTagged};
return access;
}
......@@ -301,8 +299,8 @@ ElementAccess AccessBuilder::ForSeqStringChar(String::Encoding encoding) {
// static
FieldAccess AccessBuilder::ForStatsCounter() {
FieldAccess access = {kUntaggedBase, 0, MaybeHandle<Name>(), Type::Signed32(),
kMachInt32};
FieldAccess access = {kUntaggedBase, 0, MaybeHandle<Name>(),
TypeCache::Get().kInt32, kMachInt32};
return access;
}
......
......@@ -41,7 +41,7 @@ class AccessBuilder final : public AllStatic {
static FieldAccess ForJSDateField(JSDate::FieldIndex index);
// Provides access to FixedArray::length() field.
static FieldAccess ForFixedArrayLength(Zone* zone);
static FieldAccess ForFixedArrayLength();
// Provides access to DescriptorArray::enum_cache() field.
static FieldAccess ForDescriptorArrayEnumCache();
......@@ -50,7 +50,7 @@ class AccessBuilder final : public AllStatic {
static FieldAccess ForDescriptorArrayEnumCacheBridgeCache();
// Provides access to Map::bit_field3() field.
static FieldAccess ForMapBitField3(Zone* zone);
static FieldAccess ForMapBitField3();
// Provides access to Map::descriptors() field.
static FieldAccess ForMapDescriptors();
......@@ -59,7 +59,7 @@ class AccessBuilder final : public AllStatic {
static FieldAccess ForMapInstanceType();
// Provides access to String::length() field.
static FieldAccess ForStringLength(Zone* zone);
static FieldAccess ForStringLength();
// Provides access to GlobalObject::global_proxy() field.
static FieldAccess ForGlobalObjectGlobalProxy();
......
......@@ -318,8 +318,7 @@ Reduction JSIntrinsicLowering::ReduceStringGetLength(Node* node) {
Node* value = NodeProperties::GetValueInput(node, 0);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
return Change(node, simplified()->LoadField(
AccessBuilder::ForStringLength(graph()->zone())),
return Change(node, simplified()->LoadField(AccessBuilder::ForStringLength()),
value, effect, control);
}
......
......@@ -13,6 +13,7 @@
#include "src/field-index-inl.h"
#include "src/lookup.h"
#include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker!
#include "src/type-cache.h"
#include "src/type-feedback-vector.h"
namespace v8 {
......@@ -36,7 +37,8 @@ JSNativeContextSpecialization::JSNativeContextSpecialization(
global_object_(global_object),
native_context_(global_object->native_context(), isolate()),
dependencies_(dependencies),
zone_(zone) {}
zone_(zone),
type_cache_(TypeCache::Get()) {}
Reduction JSNativeContextSpecialization::Reduce(Node* node) {
......@@ -114,11 +116,9 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) {
if (property_details.cell_type() == PropertyCellType::kConstantType) {
// Compute proper type based on the current value in the cell.
if (property_cell_value->IsSmi()) {
property_cell_value_type = Type::Intersect(
Type::SignedSmall(), Type::TaggedSigned(), graph()->zone());
property_cell_value_type = type_cache_.kSmi;
} else if (property_cell_value->IsNumber()) {
property_cell_value_type = Type::Intersect(
Type::Number(), Type::TaggedPointer(), graph()->zone());
property_cell_value_type = type_cache_.kHeapNumber;
} else {
Handle<Map> property_cell_value_map(
Handle<HeapObject>::cast(property_cell_value)->map(), isolate());
......@@ -331,9 +331,7 @@ bool JSNativeContextSpecialization::ComputePropertyAccessInfo(
DCHECK(Name::Equals(factory()->length_string(), name));
// The String::length property is always a smi in the range
// [0, String::kMaxLength].
field_type = Type::Intersect(
Type::Range(0.0, String::kMaxLength, graph()->zone()),
Type::TaggedSigned(), graph()->zone());
field_type = type_cache_.kStringLengthType;
} else if (map->IsJSArrayMap()) {
DCHECK(Name::Equals(factory()->length_string(), name));
// The JSArray::length property is a smi in the range
......@@ -341,17 +339,13 @@ bool JSNativeContextSpecialization::ComputePropertyAccessInfo(
// elements, a smi in the range [0, FixedArray::kMaxLength]
// in case of other fast elements, and [0, kMaxUInt32] in
// case of other arrays.
Type* field_type_rep = Type::Tagged();
double field_type_upper = kMaxUInt32;
if (IsFastElementsKind(map->elements_kind())) {
field_type_rep = Type::TaggedSigned();
field_type_upper = IsFastDoubleElementsKind(map->elements_kind())
? FixedDoubleArray::kMaxLength
: FixedArray::kMaxLength;
}
field_type =
Type::Intersect(Type::Range(0.0, field_type_upper, graph()->zone()),
field_type_rep, graph()->zone());
if (IsFastDoubleElementsKind(map->elements_kind())) {
field_type = type_cache_.kFixedDoubleArrayLengthType;
} else if (IsFastElementsKind(map->elements_kind())) {
field_type = type_cache_.kFixedArrayLengthType;
} else {
field_type = type_cache_.kJSArrayLengthType;
}
}
*access_info = PropertyAccessInfo::DataField(receiver_type, field_index,
field_type, holder);
......@@ -382,15 +376,13 @@ bool JSNativeContextSpecialization::ComputePropertyAccessInfo(
*map, index, field_representation.IsDouble());
Type* field_type = Type::Tagged();
if (field_representation.IsSmi()) {
field_type = Type::Intersect(Type::SignedSmall(),
Type::TaggedSigned(), graph()->zone());
field_type = type_cache_.kSmi;
} else if (field_representation.IsDouble()) {
if (access_mode == kStore) {
// TODO(bmeurer): Add support for storing to double fields.
break;
}
field_type = Type::Intersect(Type::Number(), Type::UntaggedFloat64(),
graph()->zone());
field_type = type_cache_.kFloat64;
} else if (field_representation.IsHeapObject()) {
// Extract the field type from the property details (make sure its
// representation is TaggedPointer to reflect the heap object case).
......
......@@ -15,6 +15,7 @@ namespace internal {
// Forward declarations.
class CompilationDependencies;
class Factory;
class TypeCache;
namespace compiler {
......@@ -101,6 +102,7 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
Handle<Context> native_context_;
CompilationDependencies* const dependencies_;
Zone* const zone_;
TypeCache const& type_cache_;
DISALLOW_COPY_AND_ASSIGN(JSNativeContextSpecialization);
};
......
......@@ -61,8 +61,7 @@ class AllocationBuilder final {
void AllocateArray(int length, Handle<Map> map) {
Allocate(FixedArray::SizeFor(length));
Store(AccessBuilder::ForMap(), map);
Store(AccessBuilder::ForFixedArrayLength(graph()->zone()),
jsgraph()->Constant(length));
Store(AccessBuilder::ForFixedArrayLength(), jsgraph()->Constant(length));
}
// Compound store of a constant into a field.
......@@ -702,7 +701,7 @@ Reduction JSTypedLowering::ReduceJSUnaryNot(Node* node) {
return Changed(node);
} else if (input_type->Is(Type::String())) {
// JSUnaryNot(x:string) => NumberEqual(x.length,#0)
FieldAccess const access = AccessBuilder::ForStringLength(graph()->zone());
FieldAccess const access = AccessBuilder::ForStringLength();
// It is safe for the load to be effect-free (i.e. not linked into effect
// chain) because we assume String::length to be immutable.
Node* length = graph()->NewNode(simplified()->LoadField(access), input,
......@@ -736,7 +735,7 @@ Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
return Changed(node);
} else if (input_type->Is(Type::String())) {
// JSToBoolean(x:string) => NumberLessThan(#0,x.length)
FieldAccess const access = AccessBuilder::ForStringLength(graph()->zone());
FieldAccess const access = AccessBuilder::ForStringLength();
Node* length = graph()->NewNode(simplified()->LoadField(access), input,
effect, graph()->start());
ReplaceWithValue(node, node, length);
......@@ -855,10 +854,9 @@ Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) {
// Optimize "length" property of strings.
if (name.is_identical_to(factory()->length_string()) &&
receiver_type->Is(Type::String())) {
Node* value = effect =
graph()->NewNode(simplified()->LoadField(
AccessBuilder::ForStringLength(graph()->zone())),
receiver, effect, control);
Node* value = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForStringLength()), receiver,
effect, control);
ReplaceWithValue(node, value, effect);
return Replace(value);
}
......@@ -1645,10 +1643,9 @@ Reduction JSTypedLowering::ReduceJSForInPrepare(Node* node) {
Node* etrue0;
{
// Enum cache case.
Node* cache_type_enum_length = etrue0 =
graph()->NewNode(simplified()->LoadField(
AccessBuilder::ForMapBitField3(graph()->zone())),
cache_type, effect, if_true0);
Node* cache_type_enum_length = etrue0 = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForMapBitField3()), cache_type,
effect, if_true0);
cache_length_true0 = graph()->NewNode(
simplified()->NumberBitwiseAnd(), cache_type_enum_length,
jsgraph()->Int32Constant(Map::EnumLengthBits::kMask));
......@@ -1718,8 +1715,7 @@ Reduction JSTypedLowering::ReduceJSForInPrepare(Node* node) {
cache_array_false0 = cache_type;
cache_length_false0 = efalse0 = graph()->NewNode(
simplified()->LoadField(
AccessBuilder::ForFixedArrayLength(graph()->zone())),
simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
cache_array_false0, efalse0, if_false0);
}
......
......@@ -5,7 +5,6 @@
#include "src/compiler/typer.h"
#include "src/base/flags.h"
#include "src/base/lazy-instance.h"
#include "src/bootstrapper.h"
#include "src/compilation-dependencies.h"
#include "src/compiler/common-operator.h"
......@@ -15,19 +14,12 @@
#include "src/compiler/node-properties.h"
#include "src/compiler/simplified-operator.h"
#include "src/objects-inl.h"
#include "src/zone-type-cache.h"
#include "src/type-cache.h"
namespace v8 {
namespace internal {
namespace compiler {
namespace {
base::LazyInstance<ZoneTypeCache>::type kCache = LAZY_INSTANCE_INITIALIZER;
} // namespace
class Typer::Decorator final : public GraphDecorator {
public:
explicit Decorator(Typer* typer) : typer_(typer) {}
......@@ -47,7 +39,7 @@ Typer::Typer(Isolate* isolate, Graph* graph, Flags flags,
dependencies_(dependencies),
function_type_(function_type),
decorator_(nullptr),
cache_(kCache.Get()) {
cache_(TypeCache::Get()) {
Zone* zone = this->zone();
Factory* const factory = isolate->factory();
......
......@@ -14,7 +14,7 @@ namespace internal {
// Forward declarations.
class CompilationDependencies;
class ZoneTypeCache;
class TypeCache;
namespace compiler {
......@@ -54,7 +54,7 @@ class Typer {
CompilationDependencies* const dependencies_;
Type::FunctionType* function_type_;
Decorator* decorator_;
ZoneTypeCache const& cache_;
TypeCache const& cache_;
Type* singleton_false_;
Type* singleton_true_;
......
// Copyright 2015 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.
#include "src/type-cache.h"
#include "src/base/lazy-instance.h"
#include "src/types-inl.h"
namespace v8 {
namespace internal {
namespace {
base::LazyInstance<TypeCache>::type kCache = LAZY_INSTANCE_INITIALIZER;
} // namespace
// static
TypeCache const& TypeCache::Get() { return kCache.Get(); }
} // namespace internal
} // namespace v8
......@@ -2,22 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_ZONE_TYPE_CACHE_H_
#define V8_ZONE_TYPE_CACHE_H_
#ifndef V8_TYPE_CACHE_H_
#define V8_TYPE_CACHE_H_
#include "src/types.h"
namespace v8 {
namespace internal {
class ZoneTypeCache final {
class TypeCache final {
private:
// This has to be first for the initialization magic to work.
Zone zone_;
public:
ZoneTypeCache() = default;
static TypeCache const& Get();
TypeCache() = default;
Type* const kInt8 =
CreateNative(CreateRange<int8_t>(), Type::UntaggedSigned8());
......@@ -34,6 +35,9 @@ class ZoneTypeCache final {
Type* const kFloat32 = CreateNative(Type::Number(), Type::UntaggedFloat32());
Type* const kFloat64 = CreateNative(Type::Number(), Type::UntaggedFloat64());
Type* const kSmi = CreateNative(Type::SignedSmall(), Type::TaggedSigned());
Type* const kHeapNumber = CreateNative(Type::Number(), Type::TaggedPointer());
Type* const kSingletonZero = CreateRange(0.0, 0.0);
Type* const kSingletonOne = CreateRange(1.0, 1.0);
Type* const kZeroOrOne = CreateRange(0.0, 1.0);
......@@ -43,6 +47,26 @@ class ZoneTypeCache final {
Type* const kInteger = CreateRange(-V8_INFINITY, V8_INFINITY);
Type* const kWeakint = Type::Union(kInteger, Type::MinusZeroOrNaN(), zone());
// The FixedArray::length property always containts a smi in the range
// [0, FixedArray::kMaxLength].
Type* const kFixedArrayLengthType = CreateNative(
CreateRange(0.0, FixedArray::kMaxLength), Type::TaggedSigned());
// The FixedDoubleArray::length property always containts a smi in the range
// [0, FixedDoubleArray::kMaxLength].
Type* const kFixedDoubleArrayLengthType = CreateNative(
CreateRange(0.0, FixedDoubleArray::kMaxLength), Type::TaggedSigned());
// The JSArray::length property always contains a tagged number in the range
// [0, kMaxUInt32].
Type* const kJSArrayLengthType =
CreateNative(CreateRange(0.0, kMaxUInt32), Type::Tagged());
// The String::length property always contains a smi in the range
// [0, String::kMaxLength].
Type* const kStringLengthType =
CreateNative(CreateRange(0.0, String::kMaxLength), Type::TaggedSigned());
#define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \
Type* const k##TypeName##Array = CreateArray(k##TypeName);
TYPED_ARRAYS(TYPED_ARRAY)
......@@ -78,4 +102,4 @@ class ZoneTypeCache final {
} // namespace internal
} // namespace v8
#endif // V8_ZONE_TYPE_CACHE_H_
#endif // V8_TYPE_CACHE_H_
......@@ -9,16 +9,10 @@
#include "src/ast.h"
#include "src/codegen.h"
#include "src/scopes.h"
#include "src/zone-type-cache.h"
#include "src/type-cache.h"
namespace v8 {
namespace internal {
namespace {
base::LazyInstance<ZoneTypeCache>::type kCache = LAZY_INSTANCE_INITIALIZER;
} // namespace
#define FAIL(node, msg) \
do { \
......@@ -58,7 +52,7 @@ AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script,
ZoneAllocationPolicy(zone)),
in_function_(false),
building_function_tables_(false),
cache_(kCache.Get()) {
cache_(TypeCache::Get()) {
InitializeAstVisitor(isolate);
InitializeStdlib();
}
......
......@@ -15,7 +15,7 @@
namespace v8 {
namespace internal {
class ZoneTypeCache;
class TypeCache;
class AsmTyper : public AstVisitor {
public:
......@@ -52,7 +52,7 @@ class AsmTyper : public AstVisitor {
bool in_function_; // In module function?
bool building_function_tables_;
ZoneTypeCache const& cache_;
TypeCache const& cache_;
static const int kErrorMessageLimit = 100;
char error_message_[kErrorMessageLimit];
......
......@@ -9,8 +9,8 @@
#include "src/parser.h"
#include "src/rewriter.h"
#include "src/scopes.h"
#include "src/type-cache.h"
#include "src/typing-asm.h"
#include "src/zone-type-cache.h"
#include "test/cctest/cctest.h"
#include "test/cctest/expression-type-collector.h"
#include "test/cctest/expression-type-collector-macros.h"
......@@ -116,7 +116,7 @@ TEST(ValidateMinimum) {
Zone* zone = handles.main_zone();
ZoneVector<ExpressionTypeEntry> types(zone);
CHECK_EQ("", Validate(zone, test_function, &types));
ZoneTypeCache cache;
TypeCache cache;
CHECK_TYPES_BEGIN {
// Module.
......@@ -395,7 +395,7 @@ TEST(ValidateMinimum) {
namespace {
void CheckStdlibShortcuts(Zone* zone, ZoneVector<ExpressionTypeEntry>& types,
size_t& index, int& depth, ZoneTypeCache& cache) {
size_t& index, int& depth, TypeCache& cache) {
// var exp = stdlib.*; (D * 12)
CHECK_VAR_SHORTCUT(Infinity, Bounds(cache.kFloat64));
CHECK_VAR_SHORTCUT(NaN, Bounds(cache.kFloat64));
......@@ -452,7 +452,7 @@ void CheckStdlibShortcuts(Zone* zone, ZoneVector<ExpressionTypeEntry>& types,
Zone* zone = handles.main_zone(); \
ZoneVector<ExpressionTypeEntry> types(zone); \
CHECK_EQ("", Validate(zone, test_function, &types)); \
ZoneTypeCache cache; \
TypeCache cache; \
\
CHECK_TYPES_BEGIN { \
/* Module. */ \
......
......@@ -373,9 +373,8 @@ TEST_F(JSIntrinsicLoweringTest, InlineStringGetLength) {
javascript()->CallRuntime(Runtime::kInlineStringGetLength, 1), input,
context, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsLoadField(AccessBuilder::ForStringLength(zone()), input, effect,
control));
EXPECT_THAT(r.replacement(), IsLoadField(AccessBuilder::ForStringLength(),
input, effect, control));
}
......
......@@ -191,9 +191,8 @@ TEST_F(JSTypedLoweringTest, JSUnaryNotWithString) {
Reduction r = Reduce(graph()->NewNode(javascript()->UnaryNot(), input,
context, graph()->start()));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsNumberEqual(IsLoadField(AccessBuilder::ForStringLength(zone()), input,
EXPECT_THAT(r.replacement(),
IsNumberEqual(IsLoadField(AccessBuilder::ForStringLength(), input,
graph()->start(), graph()->start()),
IsNumberConstant(0.0)));
}
......@@ -390,8 +389,8 @@ TEST_F(JSTypedLoweringTest, JSToBooleanWithString) {
EXPECT_THAT(
r.replacement(),
IsNumberLessThan(IsNumberConstant(0.0),
IsLoadField(AccessBuilder::ForStringLength(zone()),
input, graph()->start(), graph()->start())));
IsLoadField(AccessBuilder::ForStringLength(), input,
graph()->start(), graph()->start())));
}
......@@ -881,9 +880,8 @@ TEST_F(JSTypedLoweringTest, JSLoadNamedStringLength) {
receiver, vector, context, EmptyFrameState(),
EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsLoadField(AccessBuilder::ForStringLength(zone()), receiver,
effect, control));
EXPECT_THAT(r.replacement(), IsLoadField(AccessBuilder::ForStringLength(),
receiver, effect, control));
}
}
......
......@@ -1001,6 +1001,8 @@
'../../src/transitions-inl.h',
'../../src/transitions.cc',
'../../src/transitions.h',
'../../src/type-cache.cc',
'../../src/type-cache.h',
'../../src/type-feedback-vector-inl.h',
'../../src/type-feedback-vector.cc',
'../../src/type-feedback-vector.h',
......@@ -1034,7 +1036,6 @@
'../../src/version.h',
'../../src/vm-state-inl.h',
'../../src/vm-state.h',
'../../src/zone-type-cache.h',
'../../src/zone.cc',
'../../src/zone.h',
'../../src/zone-allocator.h',
......
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