Commit 6c3c952d authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] add internal classes that map to FixedArray instances

Bug: v8:7793
Change-Id: Ifc2bf26e9d3bc13d4f2455d6d04ce5e2682626db
Reviewed-on: https://chromium-review.googlesource.com/c/1454600Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59404}
parent d09bea1b
...@@ -21,9 +21,7 @@ type Smi extends Tagged generates 'TNode<Smi>' constexpr 'Smi'; ...@@ -21,9 +21,7 @@ type Smi extends Tagged generates 'TNode<Smi>' constexpr 'Smi';
// A Smi that is greater than or equal to 0. See TaggedIsPositiveSmi. // A Smi that is greater than or equal to 0. See TaggedIsPositiveSmi.
type PositiveSmi extends Smi generates 'TNode<Smi>'; type PositiveSmi extends Smi generates 'TNode<Smi>';
class HeapObject extends Tagged { extern class HeapObject extends Tagged { map: Map; }
map: Map;
}
type Object = Smi | HeapObject; type Object = Smi | HeapObject;
type int32 generates 'TNode<Int32T>' constexpr 'int32_t'; type int32 generates 'TNode<Int32T>' constexpr 'int32_t';
...@@ -69,25 +67,26 @@ type RootIndex generates 'TNode<Int32T>' constexpr 'RootIndex'; ...@@ -69,25 +67,26 @@ type RootIndex generates 'TNode<Int32T>' constexpr 'RootIndex';
type Map extends HeapObject generates 'TNode<Map>'; type Map extends HeapObject generates 'TNode<Map>';
type FixedArrayBase extends HeapObject generates 'TNode<FixedArrayBase>';
type FixedArray extends FixedArrayBase generates 'TNode<FixedArray>';
type FixedDoubleArray extends FixedArrayBase
generates 'TNode<FixedDoubleArray>';
// These intrinsics should never be called from Torque code. They're used // These intrinsics should never be called from Torque code. They're used
// internally by the 'new' operator and only declared here because it's simpler // internally by the 'new' operator and only declared here because it's simpler
// than building the definition from C++. // than building the definition from C++.
intrinsic %GetAllocationBaseSize<Class: type>(map: Map): intptr; intrinsic %GetAllocationBaseSize<Class: type>(map: Map): intptr;
intrinsic %Allocate<Class: type>(size: intptr): Class; intrinsic %Allocate<Class: type>(size: intptr): Class;
intrinsic %AllocateInternalClass<Class: type>(slotCount: constexpr intptr): Class;
type FixedArrayBase extends HeapObject generates 'TNode<FixedArrayBase>'; extern class JSReceiver extends HeapObject {
type FixedArray extends FixedArrayBase generates 'TNode<FixedArray>';
type FixedDoubleArray extends FixedArrayBase
generates 'TNode<FixedDoubleArray>';
class JSReceiver extends HeapObject {
properties_or_hash: FixedArrayBase | Smi; properties_or_hash: FixedArrayBase | Smi;
} }
type Constructor extends JSReceiver generates 'TNode<JSReceiver>'; type Constructor extends JSReceiver generates 'TNode<JSReceiver>';
type JSProxy extends JSReceiver generates 'TNode<JSProxy>'; type JSProxy extends JSReceiver generates 'TNode<JSProxy>';
class JSObject extends JSReceiver { extern class JSObject extends JSReceiver {
constructor( constructor(
map: Map, properties: FixedArrayBase | Smi, elements: FixedArrayBase) { map: Map, properties: FixedArrayBase | Smi, elements: FixedArrayBase) {
super(map, properties); super(map, properties);
...@@ -103,11 +102,9 @@ class JSObject extends JSReceiver { ...@@ -103,11 +102,9 @@ class JSObject extends JSReceiver {
elements: FixedArrayBase; elements: FixedArrayBase;
} }
class JSArgumentsObjectWithLength extends JSObject { extern class JSArgumentsObjectWithLength extends JSObject { length: Object; }
length: Object;
}
class JSArray extends JSObject { extern class JSArray extends JSObject {
constructor(implicit context: Context)() { constructor(implicit context: Context)() {
super( super(
GetFastPackedSmiElementsJSArrayMap(), kEmptyFixedArray, GetFastPackedSmiElementsJSArrayMap(), kEmptyFixedArray,
...@@ -143,7 +140,7 @@ type DebugInfo extends HeapObject; ...@@ -143,7 +140,7 @@ type DebugInfo extends HeapObject;
type ScopeInfo extends Object generates 'TNode<ScopeInfo>'; type ScopeInfo extends Object generates 'TNode<ScopeInfo>';
class SharedFunctionInfo extends HeapObject { extern class SharedFunctionInfo extends HeapObject {
weak function_data: Object; weak function_data: Object;
name_or_scope_info: String | NoSharedNameSentinel | ScopeInfo; name_or_scope_info: String | NoSharedNameSentinel | ScopeInfo;
outer_scope_info_or_feedback_metadata: HeapObject; outer_scope_info_or_feedback_metadata: HeapObject;
...@@ -156,11 +153,11 @@ class SharedFunctionInfo extends HeapObject { ...@@ -156,11 +153,11 @@ class SharedFunctionInfo extends HeapObject {
flags: int32; flags: int32;
} }
class SharedFunctionInfoWithID extends SharedFunctionInfo { extern class SharedFunctionInfoWithID extends SharedFunctionInfo {
unique_id: int32; unique_id: int32;
} }
class JSFunction extends JSObject { extern class JSFunction extends JSObject {
shared_function_info: SharedFunctionInfo; shared_function_info: SharedFunctionInfo;
context: Context; context: Context;
feedback_cell: Smi; feedback_cell: Smi;
...@@ -168,7 +165,7 @@ class JSFunction extends JSObject { ...@@ -168,7 +165,7 @@ class JSFunction extends JSObject {
weak prototype_or_initial_map: JSReceiver | Map; weak prototype_or_initial_map: JSReceiver | Map;
} }
class JSBoundFunction extends JSObject { extern class JSBoundFunction extends JSObject {
bound_target_function: JSReceiver; bound_target_function: JSReceiver;
bound_this: Object; bound_this: Object;
bound_arguments: FixedArray; bound_arguments: FixedArray;
...@@ -213,18 +210,18 @@ extern operator '[]=' macro StoreContextElement( ...@@ -213,18 +210,18 @@ extern operator '[]=' macro StoreContextElement(
extern operator '[]' macro LoadContextElement(Context, intptr): Object; extern operator '[]' macro LoadContextElement(Context, intptr): Object;
extern operator '[]' macro LoadContextElement(Context, Smi): Object; extern operator '[]' macro LoadContextElement(Context, Smi): Object;
class JSArrayBuffer extends JSObject { extern class JSArrayBuffer extends JSObject {
byte_length: uintptr; byte_length: uintptr;
backing_store: RawPtr; backing_store: RawPtr;
} }
class JSArrayBufferView extends JSObject { extern class JSArrayBufferView extends JSObject {
buffer: JSArrayBuffer; buffer: JSArrayBuffer;
byte_offset: uintptr; byte_offset: uintptr;
byte_length: uintptr; byte_length: uintptr;
} }
class JSTypedArray extends JSArrayBufferView {} extern class JSTypedArray extends JSArrayBufferView {}
type JSDataView extends JSArrayBufferView generates 'TNode<JSDataView>'; type JSDataView extends JSArrayBufferView generates 'TNode<JSDataView>';
......
...@@ -1217,6 +1217,12 @@ TNode<HeapObject> CodeStubAssembler::Allocate(TNode<IntPtrT> size_in_bytes, ...@@ -1217,6 +1217,12 @@ TNode<HeapObject> CodeStubAssembler::Allocate(TNode<IntPtrT> size_in_bytes,
AllocationFlags flags) { AllocationFlags flags) {
Comment("Allocate"); Comment("Allocate");
bool const new_space = !(flags & kPretenured); bool const new_space = !(flags & kPretenured);
if (!(flags & kAllowLargeObjectAllocation)) {
intptr_t size_constant;
if (ToIntPtrConstant(size_in_bytes, size_constant)) {
CHECK_LE(size_constant, kMaxRegularHeapObjectSize);
}
}
if (!(flags & kDoubleAlignment) && !(flags & kAllowLargeObjectAllocation)) { if (!(flags & kDoubleAlignment) && !(flags & kAllowLargeObjectAllocation)) {
return OptimizedAllocate(size_in_bytes, new_space return OptimizedAllocate(size_in_bytes, new_space
? PretenureFlag::NOT_TENURED ? PretenureFlag::NOT_TENURED
......
...@@ -1535,6 +1535,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -1535,6 +1535,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
fixed_array_map); fixed_array_map);
} }
TNode<FixedArray> AllocateUninitializedFixedArray(intptr_t capacity) {
return UncheckedCast<FixedArray>(AllocateFixedArray(
PACKED_ELEMENTS, IntPtrConstant(capacity), AllocationFlag::kNone));
}
TNode<FixedArray> AllocateZeroedFixedArray(TNode<IntPtrT> capacity) { TNode<FixedArray> AllocateZeroedFixedArray(TNode<IntPtrT> capacity) {
TNode<FixedArray> result = UncheckedCast<FixedArray>( TNode<FixedArray> result = UncheckedCast<FixedArray>(
AllocateFixedArray(PACKED_ELEMENTS, capacity, AllocateFixedArray(PACKED_ELEMENTS, capacity,
......
...@@ -899,20 +899,23 @@ struct StructDeclaration : Declaration { ...@@ -899,20 +899,23 @@ struct StructDeclaration : Declaration {
struct ClassDeclaration : Declaration { struct ClassDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassDeclaration) DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassDeclaration)
ClassDeclaration(SourcePosition pos, std::string name, bool transient, ClassDeclaration(SourcePosition pos, std::string name, bool is_extern,
std::string super, base::Optional<std::string> generates, bool transient, base::Optional<std::string> super,
base::Optional<std::string> generates,
std::vector<Declaration*> methods, std::vector<Declaration*> methods,
std::vector<ClassFieldExpression> fields) std::vector<ClassFieldExpression> fields)
: Declaration(kKind, pos), : Declaration(kKind, pos),
name(std::move(name)), name(std::move(name)),
is_extern(is_extern),
transient(transient), transient(transient),
super(std::move(super)), super(std::move(super)),
generates(std::move(generates)), generates(std::move(generates)),
methods(std::move(methods)), methods(std::move(methods)),
fields(std::move(fields)) {} fields(std::move(fields)) {}
std::string name; std::string name;
bool is_extern;
bool transient; bool transient;
std::string super; base::Optional<std::string> super;
base::Optional<std::string> generates; base::Optional<std::string> generates;
std::vector<Declaration*> methods; std::vector<Declaration*> methods;
std::vector<ClassFieldExpression> fields; std::vector<ClassFieldExpression> fields;
......
...@@ -244,6 +244,9 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction, ...@@ -244,6 +244,9 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
} else if (instruction.intrinsic->ExternalName() == "%Allocate") { } else if (instruction.intrinsic->ExternalName() == "%Allocate") {
out_ << "ca_.UncheckedCast<" << return_type->GetGeneratedTNodeTypeName() out_ << "ca_.UncheckedCast<" << return_type->GetGeneratedTNodeTypeName()
<< ">(CodeStubAssembler(state_).Allocate"; << ">(CodeStubAssembler(state_).Allocate";
} else if (instruction.intrinsic->ExternalName() ==
"%AllocateInternalClass") {
out_ << "CodeStubAssembler(state_).AllocateUninitializedFixedArray";
} else { } else {
ReportError("no built in intrinsic with name " + ReportError("no built in intrinsic with name " +
instruction.intrinsic->ExternalName()); instruction.intrinsic->ExternalName());
...@@ -690,14 +693,21 @@ void CSAGenerator::EmitInstruction( ...@@ -690,14 +693,21 @@ void CSAGenerator::EmitInstruction(
std::tie(field_size, size_string, machine_type) = std::tie(field_size, size_string, machine_type) =
field.GetFieldSizeInformation(); field.GetFieldSizeInformation();
out_ << field.name_and_type.type->GetGeneratedTypeName() << " " << result_name if (instruction.class_type->IsExtern()) {
<< " = " out_ << field.name_and_type.type->GetGeneratedTypeName() << " "
<< "ca_.UncheckedCast<" << result_name << " = ca_.UncheckedCast<"
<< field.name_and_type.type->GetGeneratedTNodeTypeName() << field.name_and_type.type->GetGeneratedTNodeTypeName()
<< ">(CodeStubAssembler(state_).LoadObjectField(" << ">(CodeStubAssembler(state_).LoadObjectField(" << stack->Top()
<< stack->Top() + ", " + field.aggregate->GetGeneratedTNodeTypeName() + << ", " << field.aggregate->GetGeneratedTNodeTypeName() << "::k"
"::k" + CamelifyString(field.name_and_type.name) + "Offset, " << CamelifyString(field.name_and_type.name) << "Offset, "
<< machine_type + "));\n"; << machine_type + "));\n";
} else {
out_ << field.name_and_type.type->GetGeneratedTypeName() << " "
<< result_name << " = ca_.UncheckedCast<"
<< field.name_and_type.type->GetGeneratedTNodeTypeName()
<< ">(CodeStubAssembler(state_).LoadFixedArrayElement(" << stack->Top()
<< ", " << (field.offset / kTaggedSize) << "));\n";
}
stack->Poke(stack->AboveTop() - 1, result_name); stack->Poke(stack->AboveTop() - 1, result_name);
} }
...@@ -708,26 +718,31 @@ void CSAGenerator::EmitInstruction( ...@@ -708,26 +718,31 @@ void CSAGenerator::EmitInstruction(
stack->Push(value); stack->Push(value);
const Field& field = const Field& field =
instruction.class_type->LookupField(instruction.field_name); instruction.class_type->LookupField(instruction.field_name);
if (field.name_and_type.type->IsSubtypeOf(TypeOracle::GetTaggedType())) { if (instruction.class_type->IsExtern()) {
if (field.offset == 0) { if (field.name_and_type.type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
out_ << " CodeStubAssembler(state_).StoreMap(" + object + ", " + if (field.offset == 0) {
value + ");\n"; out_ << " CodeStubAssembler(state_).StoreMap(" << object << ", "
<< value << ");\n";
} else {
out_ << " CodeStubAssembler(state_).StoreObjectField(" << object
<< ", " << field.offset << ", " << value << ");\n";
}
} else { } else {
out_ << " CodeStubAssembler(state_).StoreObjectField(" + object + size_t field_size;
", " + std::to_string(field.offset) + ", " + value + ");\n"; std::string size_string;
std::string machine_type;
std::tie(field_size, size_string, machine_type) =
field.GetFieldSizeInformation();
if (field.offset == 0) {
ReportError("the first field in a class object must be a map");
}
out_ << " CodeStubAssembler(state_).StoreObjectFieldNoWriteBarrier("
<< object << ", " << field.offset << ", " << value << ", "
<< machine_type << ".representation());\n";
} }
} else { } else {
size_t field_size; out_ << " CodeStubAssembler(state_).StoreFixedArrayElement(" << object
std::string size_string; << ", " << (field.offset / kTaggedSize) << ", " << value << ");\n";
std::string machine_type;
std::tie(field_size, size_string, machine_type) =
field.GetFieldSizeInformation();
if (field.offset == 0) {
ReportError("the first field in a class object must be a map");
}
out_ << " CodeStubAssembler(state_).StoreObjectFieldNoWriteBarrier("
<< object << ", " << std::to_string(field.offset) + ", " << value
<< ", " << machine_type << ".representation());\n";
} }
} }
......
...@@ -348,30 +348,47 @@ void DeclarationVisitor::Visit(StructDeclaration* decl) { ...@@ -348,30 +348,47 @@ void DeclarationVisitor::Visit(StructDeclaration* decl) {
} }
void DeclarationVisitor::Visit(ClassDeclaration* decl) { void DeclarationVisitor::Visit(ClassDeclaration* decl) {
// Compute the offset of the class' first member. If the class extends ClassType* new_class;
// another class, it's the size of the extended class, otherwise zero. if (decl->is_extern) {
const Type* super_type = Declarations::LookupType(decl->super); if (!decl->super) {
if (super_type != TypeOracle::GetTaggedType()) { ReportError("Extern class must extend another type.");
const ClassType* super_class = ClassType::DynamicCast(super_type); }
if (!super_class) { // Compute the offset of the class' first member. If the class extends
ReportError("class \"", decl->name, // another class, it's the size of the extended class, otherwise zero.
"\" must extend either Tagged or an already declared class"); const Type* super_type = Declarations::LookupType(*decl->super);
if (super_type != TypeOracle::GetTaggedType()) {
const ClassType* super_class = ClassType::DynamicCast(super_type);
if (!super_class) {
ReportError(
"class \"", decl->name,
"\" must extend either Tagged or an already declared class");
}
} }
}
// The generates clause must create a TNode<> // The generates clause must create a TNode<>
std::string generates = decl->name; std::string generates = decl->name;
if (decl->generates) { if (decl->generates) {
if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" || if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
generates.substr(generates.length() - 1, 1) != ">") { generates.substr(generates.length() - 1, 1) != ">") {
ReportError("generated type \"", generates, ReportError("generated type \"", generates,
"\" should be of the form \"TNode<...>\""); "\" should be of the form \"TNode<...>\"");
}
generates = generates.substr(6, generates.length() - 7);
} }
generates = generates.substr(6, generates.length() - 7);
}
auto new_class = Declarations::DeclareClass(super_type, decl->name, new_class = Declarations::DeclareClass(
decl->transient, generates); super_type, decl->name, decl->is_extern, decl->transient, generates);
} else {
if (decl->super) {
ReportError("Only extern classes can inherit.");
}
if (decl->generates) {
ReportError("Only extern classes can specify a generated type.");
}
new_class = Declarations::DeclareClass(TypeOracle::GetTaggedType(),
decl->name, decl->is_extern,
decl->transient, "FixedArray");
}
GlobalContext::RegisterClass(decl->name, new_class); GlobalContext::RegisterClass(decl->name, new_class);
class_declarations_.push_back( class_declarations_.push_back(
std::make_tuple(CurrentScope::Get(), decl, new_class)); std::make_tuple(CurrentScope::Get(), decl, new_class));
...@@ -534,6 +551,14 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods( ...@@ -534,6 +551,14 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods(
field_expression.name_and_type.type->pos); field_expression.name_and_type.type->pos);
const Type* field_type = const Type* field_type =
Declarations::GetType(field_expression.name_and_type.type); Declarations::GetType(field_expression.name_and_type.type);
if (!class_declaration->is_extern) {
if (!field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
ReportError("Non-extern classes do not support untagged fields.");
}
if (field_expression.weak) {
ReportError("Non-extern classes do not support weak fields.");
}
}
const Field& field = class_type->RegisterField( const Field& field = class_type->RegisterField(
{field_expression.name_and_type.type->pos, {field_expression.name_and_type.type->pos,
class_type, class_type,
......
...@@ -174,10 +174,11 @@ StructType* Declarations::DeclareStruct(const std::string& name) { ...@@ -174,10 +174,11 @@ StructType* Declarations::DeclareStruct(const std::string& name) {
} }
ClassType* Declarations::DeclareClass(const Type* super_type, ClassType* Declarations::DeclareClass(const Type* super_type,
const std::string& name, bool transient, const std::string& name, bool is_extern,
bool transient,
const std::string& generates) { const std::string& generates) {
ClassType* new_type = ClassType* new_type = TypeOracle::GetClassType(super_type, name, is_extern,
TypeOracle::GetClassType(super_type, name, transient, generates); transient, generates);
DeclareType(name, new_type, false); DeclareType(name, new_type, false);
return new_type; return new_type;
} }
......
...@@ -84,7 +84,8 @@ class Declarations { ...@@ -84,7 +84,8 @@ class Declarations {
static StructType* DeclareStruct(const std::string& name); static StructType* DeclareStruct(const std::string& name);
static ClassType* DeclareClass(const Type* super, const std::string& name, static ClassType* DeclareClass(const Type* super, const std::string& name,
bool transient, const std::string& generates); bool is_extern, bool transient,
const std::string& generates);
static Macro* CreateMacro(std::string external_name, static Macro* CreateMacro(std::string external_name,
std::string readable_name, std::string readable_name,
......
...@@ -150,7 +150,7 @@ void ImplementationVisitor::Visit(NamespaceConstant* decl) { ...@@ -150,7 +150,7 @@ void ImplementationVisitor::Visit(NamespaceConstant* decl) {
void ImplementationVisitor::Visit(TypeAlias* alias) { void ImplementationVisitor::Visit(TypeAlias* alias) {
if (alias->IsRedeclaration()) return; if (alias->IsRedeclaration()) return;
const ClassType* class_type = ClassType::DynamicCast(alias->type()); const ClassType* class_type = ClassType::DynamicCast(alias->type());
if (class_type) { if (class_type && class_type->IsExtern()) {
// Classes that are in the default namespace are defined in the C++ // Classes that are in the default namespace are defined in the C++
// world and all of their fields and methods are declared explicitly. // world and all of their fields and methods are declared explicitly.
// Internal classes (e.g. ones used for testing that are not in the default // Internal classes (e.g. ones used for testing that are not in the default
...@@ -170,7 +170,7 @@ void ImplementationVisitor::Visit(TypeAlias* alias) { ...@@ -170,7 +170,7 @@ void ImplementationVisitor::Visit(TypeAlias* alias) {
header_out() << " };\n"; header_out() << " };\n";
} else if (!class_type->nspace()->IsDefaultNamespace()) { } else if (!class_type->nspace()->IsDefaultNamespace()) {
ReportError( ReportError(
"classes are currently only supported in the default and test " "extern classes are currently only supported in the default and test "
"namespaces"); "namespaces");
} }
return; return;
...@@ -1281,16 +1281,26 @@ VisitResult ImplementationVisitor::Visit(NewExpression* expr) { ...@@ -1281,16 +1281,26 @@ VisitResult ImplementationVisitor::Visit(NewExpression* expr) {
// Output the code to generate an unitialized object of the class size in the // Output the code to generate an unitialized object of the class size in the
// GC heap. // GC heap.
VisitResult object_map = ProjectStructField(new_struct_result, "map"); VisitResult allocate_result;
Arguments size_arguments; if (class_type->IsExtern()) {
size_arguments.parameters.push_back(object_map); VisitResult object_map = ProjectStructField(new_struct_result, "map");
VisitResult object_size = GenerateCall("%GetAllocationBaseSize", Arguments size_arguments;
size_arguments, {class_type}, false); size_arguments.parameters.push_back(object_map);
Arguments allocate_arguments; VisitResult object_size = GenerateCall("%GetAllocationBaseSize",
allocate_arguments.parameters.push_back(object_size); size_arguments, {class_type}, false);
VisitResult allocate_result = Arguments allocate_arguments;
GenerateCall("%Allocate", allocate_arguments, {class_type}, false); allocate_arguments.parameters.push_back(object_size);
DCHECK(allocate_result.IsOnStack()); allocate_result =
GenerateCall("%Allocate", allocate_arguments, {class_type}, false);
DCHECK(allocate_result.IsOnStack());
} else {
Arguments allocate_arguments;
allocate_arguments.parameters.push_back(
VisitResult(TypeOracle::GetConstexprIntPtrType(),
std::to_string(class_type->size() / kTaggedSize)));
allocate_result = GenerateCall("%AllocateInternalClass", allocate_arguments,
{class_type}, false);
}
// Fill in the fields of the newly allocated class by copying the values // Fill in the fields of the newly allocated class by copying the values
// from the struct that was built by the constructor. So that the generaeted // from the struct that was built by the constructor. So that the generaeted
......
...@@ -591,18 +591,19 @@ base::Optional<ParseResult> MakeMethodDeclaration( ...@@ -591,18 +591,19 @@ base::Optional<ParseResult> MakeMethodDeclaration(
base::Optional<ParseResult> MakeClassDeclaration( base::Optional<ParseResult> MakeClassDeclaration(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
auto is_extern = child_results->NextAs<bool>();
auto transient = child_results->NextAs<bool>(); auto transient = child_results->NextAs<bool>();
auto name = child_results->NextAs<std::string>(); auto name = child_results->NextAs<std::string>();
if (!IsValidTypeName(name)) { if (!IsValidTypeName(name)) {
NamingConventionError("Type", name, "UpperCamelCase"); NamingConventionError("Type", name, "UpperCamelCase");
} }
auto extends = child_results->NextAs<std::string>(); auto extends = child_results->NextAs<base::Optional<std::string>>();
auto generates = child_results->NextAs<base::Optional<std::string>>(); auto generates = child_results->NextAs<base::Optional<std::string>>();
auto methods = child_results->NextAs<std::vector<Declaration*>>(); auto methods = child_results->NextAs<std::vector<Declaration*>>();
auto fields = child_results->NextAs<std::vector<ClassFieldExpression>>(); auto fields = child_results->NextAs<std::vector<ClassFieldExpression>>();
Declaration* result = MakeNode<ClassDeclaration>( Declaration* result = MakeNode<ClassDeclaration>(
std::move(name), transient, std::move(extends), std::move(generates), std::move(name), is_extern, transient, std::move(extends),
std::move(methods), fields); std::move(generates), std::move(methods), fields);
return ParseResult{result}; return ParseResult{result};
} }
...@@ -1619,8 +1620,9 @@ struct TorqueGrammar : Grammar { ...@@ -1619,8 +1620,9 @@ struct TorqueGrammar : Grammar {
Rule({Token("const"), &identifier, Token(":"), &type, Token("generates"), Rule({Token("const"), &identifier, Token(":"), &type, Token("generates"),
&externalString, Token(";")}, &externalString, Token(";")},
MakeExternConstDeclaration), MakeExternConstDeclaration),
Rule({CheckIf(Token("transient")), Token("class"), &identifier, Rule({CheckIf(Token("extern")), CheckIf(Token("transient")),
Sequence({Token("extends"), &identifier}), Token("class"), &identifier,
Optional<std::string>(Sequence({Token("extends"), &identifier})),
Optional<std::string>( Optional<std::string>(
Sequence({Token("generates"), &externalString})), Sequence({Token("generates"), &externalString})),
Token("{"), List<Declaration*>(&method), Token("{"), List<Declaration*>(&method),
......
...@@ -35,9 +35,10 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -35,9 +35,10 @@ class TypeOracle : public ContextualClass<TypeOracle> {
} }
static ClassType* GetClassType(const Type* parent, const std::string& name, static ClassType* GetClassType(const Type* parent, const std::string& name,
bool transient, const std::string& generates) { bool is_extern, bool transient,
ClassType* result = const std::string& generates) {
new ClassType(parent, CurrentNamespace(), name, transient, generates); ClassType* result = new ClassType(parent, CurrentNamespace(), name,
is_extern, transient, generates);
Get().struct_types_.push_back(std::unique_ptr<ClassType>(result)); Get().struct_types_.push_back(std::unique_ptr<ClassType>(result));
return result; return result;
} }
...@@ -95,6 +96,10 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -95,6 +96,10 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return Get().GetBuiltinType(CONSTEXPR_BOOL_TYPE_STRING); return Get().GetBuiltinType(CONSTEXPR_BOOL_TYPE_STRING);
} }
static const Type* GetConstexprIntPtrType() {
return Get().GetBuiltinType(CONSTEXPR_INTPTR_TYPE_STRING);
}
static const Type* GetVoidType() { static const Type* GetVoidType() {
return Get().GetBuiltinType(VOID_TYPE_STRING); return Get().GetBuiltinType(VOID_TYPE_STRING);
} }
......
...@@ -262,6 +262,7 @@ std::string StructType::ToExplicitString() const { ...@@ -262,6 +262,7 @@ std::string StructType::ToExplicitString() const {
} }
std::string ClassType::GetGeneratedTNodeTypeName() const { std::string ClassType::GetGeneratedTNodeTypeName() const {
if (!IsExtern()) return generates_;
std::string prefix = nspace()->IsDefaultNamespace() std::string prefix = nspace()->IsDefaultNamespace()
? std::string{} ? std::string{}
: (nspace()->ExternalName() + "::"); : (nspace()->ExternalName() + "::");
...@@ -282,7 +283,7 @@ std::string ClassType::ToExplicitString() const { ...@@ -282,7 +283,7 @@ std::string ClassType::ToExplicitString() const {
} }
bool ClassType::AllowInstantiation() const { bool ClassType::AllowInstantiation() const {
return nspace()->IsDefaultNamespace(); return !IsExtern() || nspace()->IsDefaultNamespace();
} }
void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) { void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) {
......
...@@ -22,6 +22,7 @@ namespace torque { ...@@ -22,6 +22,7 @@ namespace torque {
static const char* const CONSTEXPR_TYPE_PREFIX = "constexpr "; static const char* const CONSTEXPR_TYPE_PREFIX = "constexpr ";
static const char* const NEVER_TYPE_STRING = "never"; static const char* const NEVER_TYPE_STRING = "never";
static const char* const CONSTEXPR_BOOL_TYPE_STRING = "constexpr bool"; static const char* const CONSTEXPR_BOOL_TYPE_STRING = "constexpr bool";
static const char* const CONSTEXPR_INTPTR_TYPE_STRING = "constexpr intptr";
static const char* const BOOL_TYPE_STRING = "bool"; static const char* const BOOL_TYPE_STRING = "bool";
static const char* const VOID_TYPE_STRING = "void"; static const char* const VOID_TYPE_STRING = "void";
static const char* const ARGUMENTS_TYPE_STRING = "constexpr Arguments"; static const char* const ARGUMENTS_TYPE_STRING = "constexpr Arguments";
...@@ -471,6 +472,7 @@ class ClassType final : public AggregateType { ...@@ -471,6 +472,7 @@ class ClassType final : public AggregateType {
std::string ToExplicitString() const override; std::string ToExplicitString() const override;
std::string GetGeneratedTypeName() const override; std::string GetGeneratedTypeName() const override;
std::string GetGeneratedTNodeTypeName() const override; std::string GetGeneratedTNodeTypeName() const override;
bool IsExtern() const { return is_extern_; }
bool IsTransient() const override { return transient_; } bool IsTransient() const override { return transient_; }
size_t size() const { return size_; } size_t size() const { return size_; }
StructType* struct_type() const { return this_struct_; } StructType* struct_type() const { return this_struct_; }
...@@ -485,9 +487,10 @@ class ClassType final : public AggregateType { ...@@ -485,9 +487,10 @@ class ClassType final : public AggregateType {
private: private:
friend class TypeOracle; friend class TypeOracle;
ClassType(const Type* parent, Namespace* nspace, const std::string& name, ClassType(const Type* parent, Namespace* nspace, const std::string& name,
bool transient, const std::string& generates) bool is_extern, bool transient, const std::string& generates)
: AggregateType(Kind::kClassType, parent, nspace, name), : AggregateType(Kind::kClassType, parent, nspace, name),
this_struct_(nullptr), this_struct_(nullptr),
is_extern_(is_extern),
transient_(transient), transient_(transient),
size_(0), size_(0),
generates_(generates) { generates_(generates) {
...@@ -495,6 +498,7 @@ class ClassType final : public AggregateType { ...@@ -495,6 +498,7 @@ class ClassType final : public AggregateType {
} }
StructType* this_struct_; StructType* this_struct_;
bool is_extern_;
bool transient_; bool transient_;
size_t size_; size_t size_;
const std::string generates_; const std::string generates_;
......
...@@ -423,6 +423,22 @@ TEST(TestStructConstructor) { ...@@ -423,6 +423,22 @@ TEST(TestStructConstructor) {
ft.Call(); ft.Call();
} }
TEST(TestInternalClass) {
CcTest::InitializeVM();
Isolate* isolate(CcTest::i_isolate());
i::HandleScope scope(isolate);
Handle<Context> context =
Utils::OpenHandle(*v8::Isolate::GetCurrent()->GetCurrentContext());
CodeAssemblerTester asm_tester(isolate);
TestTorqueAssembler m(asm_tester.state());
{
m.TestInternalClass(m.UncheckedCast<Context>(m.HeapConstant(context)));
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
ft.Call();
}
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -774,7 +774,7 @@ namespace test { ...@@ -774,7 +774,7 @@ namespace test {
assert(w.d == 2); assert(w.d == 2);
} }
class TestClassWithAllTypes extends JSObject { extern class TestClassWithAllTypes extends JSObject {
a: int8; a: int8;
b: uint8; b: uint8;
b2: uint8; b2: uint8;
...@@ -810,4 +810,25 @@ namespace test { ...@@ -810,4 +810,25 @@ namespace test {
t.h = t.h; t.h = t.h;
t.i = t.i; t.i = t.i;
} }
class InternalClass {
constructor(x: Smi) {
this.a = x;
this.b = x + 1;
}
Flip() labels NotASmi {
const tmp = Cast<Smi>(this.b) otherwise NotASmi;
this.b = this.a;
this.a = tmp;
}
a: Smi;
b: Number;
}
macro TestInternalClass(implicit context: Context)() {
const o = new InternalClass{5};
o.Flip() otherwise unreachable;
check(o.a == 6);
check(o.b == 5);
}
} }
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