Commit 5bf81318 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] split base.tq

This creates a .tq file in src/objects for each src/objects/*.h file
with Torque-defined classes and moves the object definitions and
corresponding helpers/macros there.
In addition, we create files convert.tq and cast.tq in src/builtins
to move the casts and conversions to.

Since Torque-generated .cc files end up as .o files in the same
directory, there cannot be two .tq files of the same name. Thus it
was necessary to rename src/builtins/arguments.tq and
src/builtins/string.tq to not clash with the new files in src/objects.

This is a mechanical change that only moves code.

Design doc: http://doc/1fh4OUMjQMnQdJm3aiAPXQUNdgbQugkRGdJzDh8hmyzk

Bug: v8:9861 v8:9810 v8:7793
Change-Id: I9c54cb50f32b9ae0fb41752199515133eb59ea5c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1910100Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64892}
parent b98a3046
......@@ -920,7 +920,6 @@ action("postmortem-metadata") {
}
torque_files = [
"src/builtins/arguments.tq",
"src/builtins/array-copywithin.tq",
"src/builtins/array-every.tq",
"src/builtins/array-filter.tq",
......@@ -944,10 +943,14 @@ torque_files = [
"src/builtins/base.tq",
"src/builtins/bigint.tq",
"src/builtins/boolean.tq",
"src/builtins/builtins-string.tq",
"src/builtins/collections.tq",
"src/builtins/cast.tq",
"src/builtins/convert.tq",
"src/builtins/console.tq",
"src/builtins/data-view.tq",
"src/builtins/frames.tq",
"src/builtins/frame-arguments.tq",
"src/builtins/growable-fixed-array.tq",
"src/builtins/internal-coverage.tq",
"src/builtins/iterator.tq",
......@@ -978,7 +981,6 @@ torque_files = [
"src/builtins/regexp-split.tq",
"src/builtins/regexp-test.tq",
"src/builtins/regexp.tq",
"src/builtins/string.tq",
"src/builtins/string-endswith.tq",
"src/builtins/string-html.tq",
"src/builtins/string-iterator.tq",
......@@ -1006,7 +1008,59 @@ torque_files = [
"src/builtins/typed-array-some.tq",
"src/builtins/typed-array-subarray.tq",
"src/builtins/typed-array.tq",
"src/ic/handler-configuration.tq",
"src/objects/allocation-site.tq",
"src/objects/api-callbacks.tq",
"src/objects/arguments.tq",
"src/objects/cell.tq",
"src/objects/code.tq",
"src/objects/contexts.tq",
"src/objects/data-handler.tq",
"src/objects/debug-objects.tq",
"src/objects/descriptor-array.tq",
"src/objects/embedder-data-array.tq",
"src/objects/feedback-cell.tq",
"src/objects/feedback-vector.tq",
"src/objects/fixed-array.tq",
"src/objects/foreign.tq",
"src/objects/free-space.tq",
"src/objects/heap-number.tq",
"src/objects/heap-object.tq",
"src/objects/intl-objects.tq",
"src/objects/js-array-buffer.tq",
"src/objects/js-array.tq",
"src/objects/js-collection-iterator.tq",
"src/objects/js-collection.tq",
"src/objects/js-generator.tq",
"src/objects/js-objects.tq",
"src/objects/js-promise.tq",
"src/objects/js-proxy.tq",
"src/objects/js-regexp-string-iterator.tq",
"src/objects/js-regexp.tq",
"src/objects/js-weak-refs.tq",
"src/objects/literal-objects.tq",
"src/objects/map.tq",
"src/objects/microtask.tq",
"src/objects/module.tq",
"src/objects/name.tq",
"src/objects/oddball.tq",
"src/objects/ordered-hash-table.tq",
"src/objects/primitive-heap-object.tq",
"src/objects/promise.tq",
"src/objects/property-array.tq",
"src/objects/property-cell.tq",
"src/objects/prototype-info.tq",
"src/objects/regexp-match-info.tq",
"src/objects/script.tq",
"src/objects/shared-function-info.tq",
"src/objects/source-text-module.tq",
"src/objects/stack-frame-info.tq",
"src/objects/string.tq",
"src/objects/struct.tq",
"src/objects/synthetic-module.tq",
"src/objects/template-objects.tq",
"src/objects/template.tq",
"src/wasm/wasm-objects.tq",
"test/torque/test-torque.tq",
"third_party/v8/builtins/array-sort.tq",
]
......
This diff is collapsed.
This diff is collapsed.
// Copyright 2019 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.
intrinsic %FromConstexpr<To: type, From: type>(b: From): To;
macro FromConstexpr<To: type, From: type>(o: From): To;
FromConstexpr<int31, constexpr int31>(i: constexpr int31): int31 {
return %FromConstexpr<int31>(i);
}
FromConstexpr<int32, constexpr int31>(i: constexpr int31): int32 {
return %FromConstexpr<int32>(i);
}
FromConstexpr<int32, constexpr int32>(i: constexpr int32): int32 {
return %FromConstexpr<int32>(i);
}
FromConstexpr<intptr, constexpr int31>(i: constexpr int31): intptr {
return %FromConstexpr<intptr>(i);
}
FromConstexpr<intptr, constexpr int32>(i: constexpr int32): intptr {
return %FromConstexpr<intptr>(i);
}
FromConstexpr<intptr, constexpr intptr>(i: constexpr intptr): intptr {
return %FromConstexpr<intptr>(i);
}
FromConstexpr<uintptr, constexpr uintptr>(i: constexpr uintptr): uintptr {
return %FromConstexpr<uintptr>(i);
}
FromConstexpr<Smi, constexpr int31>(i: constexpr int31): Smi {
return %FromConstexpr<Smi>(i);
}
FromConstexpr<PositiveSmi, constexpr int31>(i: constexpr int31): PositiveSmi {
assert(i >= 0);
return %FromConstexpr<PositiveSmi>(i);
}
FromConstexpr<String, constexpr string>(s: constexpr string): String {
return %FromConstexpr<String>(s);
}
FromConstexpr<Number, constexpr uint32>(i: constexpr uint32): Number {
return %FromConstexpr<Number>(i);
}
FromConstexpr<Number, constexpr int32>(i: constexpr int32): Number {
return %FromConstexpr<Number>(i);
}
FromConstexpr<Number, constexpr float64>(f: constexpr float64): Number {
return %FromConstexpr<Number>(f);
}
FromConstexpr<Number, constexpr int31>(i: constexpr int31): Number {
return %FromConstexpr<Number>(i);
}
FromConstexpr<Number, constexpr Smi>(s: constexpr Smi): Number {
return SmiConstant(s);
}
FromConstexpr<Smi, constexpr Smi>(s: constexpr Smi): Smi {
return SmiConstant(s);
}
FromConstexpr<uint32, constexpr int31>(i: constexpr int31): uint32 {
return Unsigned(Int32Constant(i));
}
FromConstexpr<uintptr, constexpr int31>(i: constexpr int31): uintptr {
return ChangeUint32ToWord(i);
}
FromConstexpr<float64, constexpr int31>(i: constexpr int31): float64 {
return Float64Constant(i);
}
FromConstexpr<float64, constexpr float64>(i: constexpr float64): float64 {
return Float64Constant(i);
}
FromConstexpr<bool, constexpr bool>(b: constexpr bool): bool {
return BoolConstant(b);
}
FromConstexpr<LanguageMode, constexpr LanguageMode>(m: constexpr LanguageMode):
LanguageMode {
return %RawDownCast<LanguageMode>(%FromConstexpr<Smi>(m));
}
FromConstexpr<ElementsKind, constexpr ElementsKind>(e: constexpr ElementsKind):
ElementsKind {
return Int32Constant(e);
}
FromConstexpr<Object, constexpr string>(s: constexpr string): Object {
return StringConstant(s);
}
FromConstexpr<JSAny, constexpr string>(s: constexpr string): JSAny {
return StringConstant(s);
}
FromConstexpr<NativeContextSlot, constexpr NativeContextSlot>(
c: constexpr NativeContextSlot): NativeContextSlot {
return IntPtrConstant(c);
}
FromConstexpr<ContextSlot, constexpr ContextSlot>(c: constexpr ContextSlot):
ContextSlot {
return IntPtrConstant(c);
}
FromConstexpr<PromiseState, constexpr PromiseState>(s: constexpr PromiseState):
PromiseState {
return %FromConstexpr<PromiseState>(s);
}
macro Convert<To: type, From: type>(i: From): To {
return i;
}
macro Convert<To: type, From: type>(i: From): To labels Overflow {
return i;
}
extern macro ConvertElementsKindToInt(ElementsKind): int32;
Convert<int32, ElementsKind>(elementsKind: ElementsKind): int32 {
return ConvertElementsKindToInt(elementsKind);
}
Convert<Number, int32>(i: int32): Number {
return ChangeInt32ToTagged(i);
}
Convert<intptr, int32>(i: int32): intptr {
return ChangeInt32ToIntPtr(i);
}
Convert<intptr, uint32>(i: uint32): intptr {
return Signed(ChangeUint32ToWord(i));
}
Convert<Smi, int32>(i: int32): Smi {
return SmiFromInt32(i);
}
Convert<Number, uint32>(ui: uint32): Number {
return ChangeUint32ToTagged(ui);
}
Convert<Smi, uint32>(ui: uint32): Smi {
return SmiFromUint32(ui);
}
Convert<uintptr, uint32>(ui: uint32): uintptr {
return ChangeUint32ToWord(ui);
}
Convert<int32, uint8>(i: uint8): int32 {
return Signed(Convert<uint32>(i));
}
Convert<int32, uint16>(i: uint16): int32 {
return Signed(Convert<uint32>(i));
}
Convert<int32, uint31>(i: uint31): int32 {
return Signed(Convert<uint32>(i));
}
Convert<int32, intptr>(i: intptr): int32 {
return TruncateIntPtrToInt32(i);
}
Convert<Smi, intptr>(i: intptr): Smi {
return SmiTag(i);
}
Convert<uint32, uintptr>(ui: uintptr): uint32 {
return Unsigned(TruncateIntPtrToInt32(Signed(ui)));
}
Convert<intptr, Smi>(s: Smi): intptr {
return SmiUntag(s);
}
Convert<uintptr, PositiveSmi>(ps: PositiveSmi): uintptr {
return Unsigned(SmiUntag(ps));
}
Convert<intptr, uintptr>(ui: uintptr): intptr {
const i = Signed(ui);
assert(i >= 0);
return i;
}
Convert<PositiveSmi, intptr>(i: intptr): PositiveSmi {
assert(IsValidPositiveSmi(i));
return %RawDownCast<PositiveSmi>(SmiTag(i));
}
Convert<PositiveSmi, uintptr>(ui: uintptr): PositiveSmi labels IfOverflow {
if (ui > kSmiMaxValue) deferred {
goto IfOverflow;
}
return %RawDownCast<PositiveSmi>(SmiTag(Signed(ui)));
}
Convert<PositiveSmi, intptr>(i: intptr): PositiveSmi labels IfOverflow {
if (IsValidPositiveSmi(i)) {
return %RawDownCast<PositiveSmi>(SmiTag(i));
} else
deferred {
goto IfOverflow;
}
}
Convert<int32, Smi>(s: Smi): int32 {
return SmiToInt32(s);
}
Convert<float64, HeapNumber>(h: HeapNumber): float64 {
return LoadHeapNumberValue(h);
}
Convert<float64, Number>(n: Number): float64 {
return ChangeNumberToFloat64(n);
}
Convert<uintptr, Number>(n: Number): uintptr {
return ChangeUintPtrNumberToUintPtr(n);
}
Convert<float64, float32>(f: float32): float64 {
return ChangeFloat32ToFloat64(f);
}
Convert<float32, float64>(f: float64): float32 {
return TruncateFloat64ToFloat32(f);
}
Convert<float32, Number>(n: Number): float32 {
return Convert<float32>(ChangeNumberToFloat64(n));
}
Convert<Number, float64>(d: float64): Number {
return AllocateHeapNumberWithValue(d);
}
Convert<float64, uintptr>(ui: uintptr): float64 {
return ChangeUintPtrToFloat64(ui);
}
Convert<Number, uintptr>(ui: uintptr): Number {
return ChangeUintPtrToTagged(ui);
}
Convert<uintptr, float64>(d: float64): uintptr {
return ChangeFloat64ToUintPtr(d);
}
Convert<uintptr, intptr>(i: intptr): uintptr {
return Unsigned(i);
}
Convert<uintptr, RawPtr>(r: RawPtr): uintptr {
return Unsigned(r);
}
Convert<intptr, RawPtr>(r: RawPtr): intptr {
return Signed(r);
}
Convert<bint, int32>(v: int32): bint {
return IntPtrToBInt(Convert<intptr>(v));
}
extern macro IntPtrToBInt(intptr): bint;
Convert<bint, intptr>(v: intptr): bint {
return IntPtrToBInt(v);
}
extern macro SmiToBInt(Smi): bint;
Convert<bint, Smi>(v: Smi): bint {
return SmiToBInt(v);
}
Convert<PromiseState, int32>(s: int32): PromiseState {
return %RawDownCast<PromiseState>(s);
}
......@@ -108,3 +108,45 @@ namespace torque_internal {
}
} // namespace torque_internal
// 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
// than building the definition from C++.
intrinsic %GetAllocationBaseSize<Class : type extends HeapObject>(map: Map):
intptr;
intrinsic %Allocate<Class : type extends HeapObject>(size: intptr): Class;
intrinsic %GetStructMap(instanceKind: constexpr InstanceType): Map;
intrinsic %AddIndexedFieldSizeToObjectSize<T: type>(
baseSize: intptr, indexSize: T, fieldSize: int32): intptr {
const convertedIndexSize = Convert<int32>(indexSize);
const variableSize: int32 =
TryInt32Mul(convertedIndexSize, fieldSize) otherwise unreachable;
const convertedVariableSize = Convert<intptr>(variableSize);
return TryIntPtrAdd(baseSize, convertedVariableSize) otherwise unreachable;
}
intrinsic
%InitializeFieldsFromIterator<Container: type, Index: type, Iterator: type>(
c: Container, length: Index, i: Iterator) {
try {
let mutableIterator = i;
let current: Index = 0;
while (current < length) {
// TODO(danno): The indexed accessor on the container requires that the
// '[]=' operator be defined explicitly for the Container
// (e.g. FixedArray). We should change this to use slice references
// once they are implemented.
c[current++] = mutableIterator.Next() otherwise NoMore;
}
}
label NoMore deferred {
unreachable;
}
}
// %RawDownCast should *never* be used anywhere in Torque code except for
// in Torque-based UnsafeCast operators preceeded by an appropriate
// type assert()
intrinsic %RawDownCast<To: type, From: type>(x: From): To;
intrinsic %RawConstexprCast<To: type, From: type>(f: From): To;
// Copyright 2019 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.
extern class LoadHandler extends DataHandler;
extern class StoreHandler extends DataHandler;
// Copyright 2019 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.
extern class AllocationSite extends Struct;
extern class AllocationMemento extends Struct {
allocation_site: AllocationSite;
}
// Copyright 2019 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.
@generateCppClass
extern class CallHandlerInfo extends Struct {
callback: NonNullForeign|Undefined|Zero;
js_callback: NonNullForeign|Undefined|Zero;
data: Object;
}
@generateCppClass
extern class InterceptorInfo extends Struct {
getter: NonNullForeign|Zero|Undefined;
setter: NonNullForeign|Zero|Undefined;
query: NonNullForeign|Zero|Undefined;
descriptor: NonNullForeign|Zero|Undefined;
deleter: NonNullForeign|Zero|Undefined;
enumerator: NonNullForeign|Zero|Undefined;
definer: NonNullForeign|Zero|Undefined;
data: Object;
flags: Smi;
}
@generateCppClass
extern class AccessCheckInfo extends Struct {
callback: Foreign|Zero|Undefined;
named_interceptor: InterceptorInfo|Zero|Undefined;
indexed_interceptor: InterceptorInfo|Zero|Undefined;
data: Object;
}
extern class AccessorInfo extends Struct {
name: Object;
flags: Smi;
expected_receiver_type: Object;
setter: NonNullForeign|Zero;
getter: NonNullForeign|Zero;
js_getter: NonNullForeign|Zero;
data: Object;
}
// Copyright 2019 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.
@generateCppClass
extern class JSArgumentsObject extends JSObject {
}
// Just a starting shape for JSObject; properties can move after initialization.
@noVerifier
@hasSameInstanceTypeAsParent
extern class JSArgumentsObjectWithLength extends JSArgumentsObject {
length: JSAny;
}
// Just a starting shape for JSObject; properties can move after initialization.
@hasSameInstanceTypeAsParent
extern class JSSloppyArgumentsObject extends JSArgumentsObjectWithLength {
callee: JSAny;
}
// Just a starting shape for JSObject; properties can move after initialization.
@hasSameInstanceTypeAsParent
@noVerifier
extern class JSStrictArgumentsObject extends JSArgumentsObjectWithLength {
}
type SloppyArgumentsElements extends FixedArray;
@generateCppClass
extern class AliasedArgumentsEntry extends Struct {
aliased_context_slot: Smi;
}
// Copyright 2019 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.
@generateCppClass
extern class Cell extends HeapObject {
value: Object;
}
// Copyright 2019 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.
@generatePrint
@generateCppClass
extern class SourcePositionTableWithFrameCache extends Struct {
source_position_table: ByteArray;
stack_frame_cache: Object;
}
type DependentCode extends WeakFixedArray;
extern class BytecodeArray extends FixedArrayBase {
// TODO(v8:8983): bytecode array object sizes vary based on their contents.
constant_pool: FixedArray;
handler_table: ByteArray;
source_position_table: Undefined|ByteArray|SourcePositionTableWithFrameCache;
frame_size: int32;
parameter_size: int32;
incoming_new_target_or_generator_register: int32;
osr_nesting_level: int8;
bytecode_age: int8;
}
extern class CodeDataContainer extends HeapObject;
// Copyright 2019 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.
@abstract
extern class Context extends HeapObject {
length: Smi;
scope_info: ScopeInfo;
previous: Object;
}
extern class AwaitContext extends Context generates 'TNode<Context>';
extern class BlockContext extends Context generates 'TNode<Context>';
extern class CatchContext extends Context generates 'TNode<Context>';
extern class DebugEvaluateContext extends Context
generates 'TNode<Context>';
extern class EvalContext extends Context generates 'TNode<Context>';
extern class FunctionContext extends Context generates 'TNode<Context>';
extern class ModuleContext extends Context generates 'TNode<Context>';
extern class NativeContext extends Context;
extern class ScriptContext extends Context generates 'TNode<Context>';
extern class WithContext extends Context generates 'TNode<Context>';
type NativeContextSlot generates 'TNode<IntPtrT>' constexpr 'int32_t';
const ARRAY_BUFFER_FUN_INDEX: constexpr NativeContextSlot
generates 'Context::ARRAY_BUFFER_FUN_INDEX';
const ARRAY_BUFFER_NOINIT_FUN_INDEX: constexpr NativeContextSlot
generates 'Context::ARRAY_BUFFER_NOINIT_FUN_INDEX';
const ARRAY_BUFFER_MAP_INDEX: constexpr NativeContextSlot
generates 'Context::ARRAY_BUFFER_MAP_INDEX';
const ARRAY_JOIN_STACK_INDEX: constexpr NativeContextSlot
generates 'Context::ARRAY_JOIN_STACK_INDEX';
const OBJECT_FUNCTION_INDEX: constexpr NativeContextSlot
generates 'Context::OBJECT_FUNCTION_INDEX';
const ITERATOR_RESULT_MAP_INDEX: constexpr NativeContextSlot
generates 'Context::ITERATOR_RESULT_MAP_INDEX';
const JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX: constexpr NativeContextSlot
generates 'Context::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX';
const JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX: constexpr NativeContextSlot
generates 'Context::JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX';
const PROXY_REVOCABLE_RESULT_MAP_INDEX: constexpr NativeContextSlot
generates 'Context::PROXY_REVOCABLE_RESULT_MAP_INDEX';
const REFLECT_APPLY_INDEX: constexpr NativeContextSlot
generates 'Context::REFLECT_APPLY_INDEX';
const REGEXP_FUNCTION_INDEX: constexpr NativeContextSlot
generates 'Context::REGEXP_FUNCTION_INDEX';
const REGEXP_LAST_MATCH_INFO_INDEX: constexpr NativeContextSlot
generates 'Context::REGEXP_LAST_MATCH_INFO_INDEX';
const INITIAL_STRING_ITERATOR_MAP_INDEX: constexpr NativeContextSlot
generates 'Context::INITIAL_STRING_ITERATOR_MAP_INDEX';
const SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP: constexpr NativeContextSlot
generates 'Context::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP';
extern operator '[]' macro LoadContextElement(
NativeContext, NativeContextSlot): Object;
extern operator '[]=' macro StoreContextElement(
NativeContext, NativeContextSlot, Object): void;
type ContextSlot generates 'TNode<IntPtrT>' constexpr 'int32_t';
const PROXY_SLOT: constexpr ContextSlot
generates 'Context::MIN_CONTEXT_SLOTS';
extern operator '[]' macro LoadContextElement(Context, ContextSlot): Object;
extern operator '[]=' macro StoreContextElement(
Context, ContextSlot, Object): void;
extern operator '[]' macro LoadContextElement(Context, intptr): Object;
extern operator '[]' macro LoadContextElement(Context, Smi): Object;
// Copyright 2019 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.
@abstract
extern class DataHandler extends Struct {
smi_handler: Smi|Code;
validity_cell: Smi|Cell;
// Space for the following fields may or may not be allocated.
@noVerifier data_1: MaybeObject;
@noVerifier data_2: MaybeObject;
@noVerifier data_3: MaybeObject;
}
// Copyright 2019 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.
@hasSameInstanceTypeAsParent
extern class BreakPoint extends Tuple2 {
}
@hasSameInstanceTypeAsParent
extern class BreakPointInfo extends Tuple2 {
}
type CoverageInfo extends FixedArray;
@generateCppClass
extern class DebugInfo extends Struct {
shared: SharedFunctionInfo;
debugger_hints: Smi;
// Script field from shared function info.
script: Undefined|Script;
// The original uninstrumented bytecode array for functions with break
// points - the instrumented bytecode is held in the shared function info.
original_bytecode_array: Undefined|BytecodeArray;
// The debug instrumented bytecode array for functions with break points
// - also pointed to by the shared function info.
debug_bytecode_array: Undefined|BytecodeArray;
// Fixed array holding status information for each active break point.
break_points: FixedArray;
flags: Smi;
coverage_info: CoverageInfo|Undefined;
}
// Copyright 2019 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.
@generatePrint
@generateCppClass
extern class EnumCache extends Struct {
keys: FixedArray;
indices: FixedArray;
}
// We make this class abstract because it is missing the variable-sized part,
// which is still impossible to express in Torque.
@abstract
@dirtyInstantiatedAbstractClass
extern class DescriptorArray extends HeapObject {
number_of_all_descriptors: uint16;
number_of_descriptors: uint16;
raw_number_of_marked_descriptors: uint16;
filler16_bits: uint16;
enum_cache: EnumCache;
// DescriptorEntry needs to be a struct with three fields.
// desriptors : DescriptorEntry[number_of_all_descriptors]
}
// Copyright 2019 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.
@generateCppClass
extern class EmbedderDataArray extends HeapObject {
length: Smi;
}
// Copyright 2019 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.
@generateCppClass
extern class FeedbackCell extends Struct {
value: Undefined|FeedbackVector|FixedArray;
interrupt_budget: int32;
}
// Copyright 2019 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.
extern class FeedbackVector extends HeapObject {
shared_function_info: SharedFunctionInfo;
optimized_code_weak_or_smi: Weak<Code>|Smi;
closure_feedback_cell_array: FixedArray;
length: int32;
invocation_count: int32;
profiler_ticks: int32;
// TODO(v8:9287) The padding is not necessary on platforms with 4 bytes
// tagged pointers, we should make it conditional; however, platform-specific
// interacts badly with GCMole, so we need to address that first.
padding: uint32;
}
extern class FeedbackMetadata extends HeapObject;
// Copyright 2019 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.
@abstract
extern class FixedArrayBase extends HeapObject {
length: Smi;
}
@abstract
@dirtyInstantiatedAbstractClass
extern class FixedArray extends FixedArrayBase {
objects[length]: Object;
}
type EmptyFixedArray extends FixedArray;
extern class FixedDoubleArray extends FixedArrayBase {
floats[length]: float64;
}
@abstract
@dirtyInstantiatedAbstractClass
extern class WeakFixedArray extends HeapObject {
length: Smi;
}
extern class ByteArray extends FixedArrayBase {}
@hasSameInstanceTypeAsParent
extern class ArrayList extends FixedArray {
}
@hasSameInstanceTypeAsParent
@noVerifier
extern class TemplateList extends FixedArray {
}
extern class WeakArrayList extends HeapObject {
capacity: Smi;
length: Smi;
objects[length]: MaybeObject;
}
extern operator '.length_intptr' macro LoadAndUntagFixedArrayBaseLength(
FixedArrayBase): intptr;
extern operator '.objects[]' macro LoadFixedArrayElement(
FixedArray, intptr): Object;
extern operator '.objects[]' macro LoadFixedArrayElement(
FixedArray, Smi): Object;
extern operator '.objects[]' macro LoadFixedArrayElement(
FixedArray, constexpr int31): Object;
extern operator '.objects[]=' macro StoreFixedArrayElement(
FixedArray, intptr, Smi): void;
extern operator '.objects[]=' macro StoreFixedArrayElement(
FixedArray, Smi, Smi): void;
extern operator '.objects[]=' macro StoreFixedArrayElement(
FixedArray, intptr, HeapObject): void;
extern operator '.objects[]=' macro StoreFixedArrayElement(
FixedArray, intptr, Object): void;
extern operator '.objects[]=' macro StoreFixedArrayElement(
FixedArray, constexpr int31, Smi): void;
extern operator '.objects[]=' macro StoreFixedArrayElement(
FixedArray, constexpr int31, HeapObject): void;
extern operator '.objects[]=' macro StoreFixedArrayElement(
FixedArray, Smi, Object): void;
extern macro StoreFixedArrayElement(
FixedArray, Smi, Object, constexpr WriteBarrierMode): void;
extern macro StoreFixedArrayElement(
FixedArray, Smi, Smi, constexpr WriteBarrierMode): void;
extern macro StoreFixedArrayElement(
FixedArray, constexpr int31, Object, constexpr WriteBarrierMode): void;
extern macro StoreFixedArrayElement(
FixedArray, constexpr int31, Smi, constexpr WriteBarrierMode): void;
extern macro StoreFixedArrayElement(
FixedArray, intptr, Object, constexpr WriteBarrierMode): void;
extern macro StoreFixedArrayElement(
FixedArray, intptr, Smi, constexpr WriteBarrierMode): void;
extern operator '.floats[]=' macro StoreFixedDoubleArrayElement(
FixedDoubleArray, intptr, float64): void;
extern operator '.floats[]=' macro StoreFixedDoubleArrayElementSmi(
FixedDoubleArray, Smi, float64): void;
extern operator '.floats[]' macro LoadFixedDoubleArrayElement(
FixedDoubleArray, intptr): float64;
operator '[]=' macro StoreFixedDoubleArrayDirect(
a: FixedDoubleArray, i: Smi, v: Number) {
a.floats[i] = Convert<float64>(v);
}
operator '[]=' macro StoreFixedArrayDirect(a: FixedArray, i: Smi, v: Object) {
a.objects[i] = v;
}
extern macro LoadDoubleWithHoleCheck(FixedDoubleArray, Smi): float64
labels IfHole;
extern macro LoadDoubleWithHoleCheck(FixedDoubleArray, intptr): float64
labels IfHole;
extern macro LoadDoubleWithHoleCheck(FixedDoubleArray, uintptr): float64
labels IfHole;
extern macro StoreFixedDoubleArrayHoleSmi(FixedDoubleArray, Smi): void;
extern macro AllocateZeroedFixedArray(intptr): FixedArray;
extern macro AllocateZeroedFixedDoubleArray(intptr): FixedDoubleArray;
extern macro CalculateNewElementsCapacity(Smi): Smi;
extern macro CalculateNewElementsCapacity(intptr): intptr;
extern macro AllocateFixedArrayWithHoles(
intptr, constexpr AllocationFlags): FixedArray;
extern macro AllocateFixedDoubleArrayWithHoles(
intptr, constexpr AllocationFlags): FixedDoubleArray;
extern macro CopyFixedArrayElements(
constexpr ElementsKind, FixedArray, constexpr ElementsKind, FixedArray,
intptr, intptr, intptr): void;
extern macro CopyFixedArrayElements(
constexpr ElementsKind, FixedArray, constexpr ElementsKind, FixedArray, Smi,
Smi, Smi): void;
extern macro ExtractFixedArray(FixedArrayBase, Smi, Smi, Smi): FixedArrayBase;
extern macro ExtractFixedArray(
FixedArrayBase, Smi, Smi, Smi,
constexpr ExtractFixedArrayFlags): FixedArrayBase;
extern macro ExtractFixedArray(
FixedArray, intptr, intptr, intptr,
constexpr ExtractFixedArrayFlags): FixedArray;
// Copyright 2019 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.
@apiExposedInstanceTypeValue(0x46)
extern class Foreign extends HeapObject {
foreign_address: RawPtr;
}
// Copyright 2019 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.
extern class FreeSpace extends HeapObject {
size: Smi;
next: FreeSpace|Uninitialized;
}
// Copyright 2019 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.
extern class HeapNumber extends PrimitiveHeapObject { value: float64; }
// The HeapNumber value NaN
type NaN extends HeapNumber;
// Copyright 2019 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.
@abstract
extern class HeapObject extends StrongTagged {
map: Map;
}
// Copyright 2019 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.
extern class JSArrayBuffer extends JSObject {
byte_length: uintptr;
backing_store: RawPtr;
}
@abstract
extern class JSArrayBufferView extends JSObject {
buffer: JSArrayBuffer;
byte_offset: uintptr;
byte_length: uintptr;
}
extern class JSTypedArray extends JSArrayBufferView {
length: uintptr;
external_pointer: RawPtr;
base_pointer: ByteArray|Smi;
}
extern class JSDataView extends JSArrayBufferView { data_pointer: RawPtr; }
// Copyright 2019 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.
extern class JSArrayIterator extends JSObject {
iterated_object: JSReceiver;
next_index: Number;
kind: Smi;
}
extern class JSArray extends JSObject {
IsEmpty(): bool {
return this.length == 0;
}
length: Number;
}
macro NewJSArray(implicit context: Context)(
map: Map, elements: FixedArrayBase): JSArray {
return new JSArray{
map,
properties_or_hash: kEmptyFixedArray,
elements,
length: elements.length
};
}
macro NewJSArray(implicit context: Context)(): JSArray {
return new JSArray{
map: GetFastPackedSmiElementsJSArrayMap(),
properties_or_hash: kEmptyFixedArray,
elements: kEmptyFixedArray,
length: 0
};
}
// A HeapObject with a JSArray map, and either fast packed elements, or fast
// holey elements when the global NoElementsProtector is not invalidated.
transient type FastJSArray extends JSArray;
// A HeapObject with a JSArray map, and either fast packed elements, or fast
// holey elements or frozen, sealed elements when the global NoElementsProtector
// is not invalidated.
transient type FastJSArrayForRead extends JSArray;
// A FastJSArray when the global ArraySpeciesProtector is not invalidated.
transient type FastJSArrayForCopy extends FastJSArray;
// A FastJSArray when the global ArrayIteratorProtector is not invalidated.
transient type FastJSArrayWithNoCustomIteration extends FastJSArray;
// A FastJSArrayForRead when the global ArrayIteratorProtector is not
// invalidated.
transient type FastJSArrayForReadWithNoCustomIteration extends
FastJSArrayForRead;
extern macro AllocateJSArray(
constexpr ElementsKind, Map, intptr, Smi,
constexpr AllocationFlags): JSArray;
extern macro AllocateJSArray(constexpr ElementsKind, Map, intptr, Smi): JSArray;
extern macro AllocateJSArray(constexpr ElementsKind, Map, Smi, Smi): JSArray;
extern macro AllocateJSArray(Map, FixedArrayBase, Smi): JSArray;
macro LoadElementNoHole<T : type extends FixedArrayBase>(
a: JSArray, index: Smi): JSAny
labels IfHole;
LoadElementNoHole<FixedArray>(implicit context: Context)(
a: JSArray, index: Smi): JSAny
labels IfHole {
try {
const elements: FixedArray =
Cast<FixedArray>(a.elements) otherwise Unexpected;
const e = UnsafeCast<(JSAny | TheHole)>(elements.objects[index]);
typeswitch (e) {
case (TheHole): {
goto IfHole;
}
case (e: JSAny): {
return e;
}
}
}
label Unexpected {
unreachable;
}
}
LoadElementNoHole<FixedDoubleArray>(implicit context: Context)(
a: JSArray, index: Smi): JSAny
labels IfHole {
try {
const elements: FixedDoubleArray =
Cast<FixedDoubleArray>(a.elements) otherwise Unexpected;
const e: float64 =
LoadDoubleWithHoleCheck(elements, index) otherwise IfHole;
return AllocateHeapNumberWithValue(e);
}
label Unexpected {
unreachable;
}
}
extern builtin ExtractFastJSArray(Context, JSArray, Smi, Smi): JSArray;
extern macro MoveElements(
constexpr ElementsKind, FixedArrayBase, intptr, intptr, intptr): void;
macro TorqueMoveElementsSmi(
elements: FixedArray, dstIndex: intptr, srcIndex: intptr,
count: intptr): void {
MoveElements(HOLEY_SMI_ELEMENTS, elements, dstIndex, srcIndex, count);
}
macro TorqueMoveElements(
elements: FixedArray, dstIndex: intptr, srcIndex: intptr,
count: intptr): void {
MoveElements(HOLEY_ELEMENTS, elements, dstIndex, srcIndex, count);
}
macro TorqueMoveElements(
elements: FixedDoubleArray, dstIndex: intptr, srcIndex: intptr,
count: intptr): void {
MoveElements(HOLEY_DOUBLE_ELEMENTS, elements, dstIndex, srcIndex, count);
}
extern macro CopyElements(
constexpr ElementsKind, FixedArrayBase, intptr, FixedArrayBase, intptr,
intptr): void;
macro TorqueCopyElements(
dstElements: FixedArray, dstIndex: intptr, srcElements: FixedArray,
srcIndex: intptr, count: intptr): void {
CopyElements(
HOLEY_ELEMENTS, dstElements, dstIndex, srcElements, srcIndex, count);
}
macro TorqueCopyElements(
dstElements: FixedDoubleArray, dstIndex: intptr,
srcElements: FixedDoubleArray, srcIndex: intptr, count: intptr): void {
CopyElements(
HOLEY_DOUBLE_ELEMENTS, dstElements, dstIndex, srcElements, srcIndex,
count);
}
extern builtin CloneFastJSArray(Context, FastJSArrayForCopy): JSArray;
struct FastJSArrayWitness {
Get(): FastJSArray {
return this.unstable;
}
Recheck() labels CastError {
if (this.stable.map != this.map) goto CastError;
// We don't need to check elements kind or whether the prototype
// has changed away from the default JSArray prototype, because
// if the map remains the same then those properties hold.
//
// However, we have to make sure there are no elements in the
// prototype chain.
if (IsNoElementsProtectorCellInvalid()) goto CastError;
this.unstable = %RawDownCast<FastJSArray>(this.stable);
}
LoadElementNoHole(implicit context: Context)(k: Smi): JSAny
labels FoundHole {
if (this.hasDoubles) {
return LoadElementNoHole<FixedDoubleArray>(this.unstable, k)
otherwise FoundHole;
} else {
return LoadElementNoHole<FixedArray>(this.unstable, k)
otherwise FoundHole;
}
}
StoreHole(k: Smi) {
if (this.hasDoubles) {
const elements = Cast<FixedDoubleArray>(this.unstable.elements)
otherwise unreachable;
StoreFixedDoubleArrayHoleSmi(elements, k);
} else {
const elements = Cast<FixedArray>(this.unstable.elements)
otherwise unreachable;
StoreFixedArrayElement(elements, k, TheHole);
}
}
LoadElementOrUndefined(implicit context: Context)(k: Smi): JSAny {
try {
return this.LoadElementNoHole(k) otherwise FoundHole;
}
label FoundHole {
return Undefined;
}
}
EnsureArrayPushable(implicit context: Context)() labels Failed {
EnsureArrayPushable(this.map) otherwise Failed;
array::EnsureWriteableFastElements(this.unstable);
this.arrayIsPushable = true;
}
ChangeLength(newLength: Smi) {
assert(this.arrayIsPushable);
this.unstable.length = newLength;
}
Push(value: JSAny) labels Failed {
assert(this.arrayIsPushable);
if (this.hasDoubles) {
BuildAppendJSArray(HOLEY_DOUBLE_ELEMENTS, this.unstable, value)
otherwise Failed;
} else if (this.hasSmis) {
BuildAppendJSArray(HOLEY_SMI_ELEMENTS, this.unstable, value)
otherwise Failed;
} else {
assert(
this.map.elements_kind == HOLEY_ELEMENTS ||
this.map.elements_kind == PACKED_ELEMENTS);
BuildAppendJSArray(HOLEY_ELEMENTS, this.unstable, value)
otherwise Failed;
}
}
MoveElements(dst: intptr, src: intptr, length: intptr) {
assert(this.arrayIsPushable);
if (this.hasDoubles) {
const elements: FixedDoubleArray =
Cast<FixedDoubleArray>(this.unstable.elements)
otherwise unreachable;
TorqueMoveElements(elements, dst, src, length);
} else {
const elements: FixedArray = Cast<FixedArray>(this.unstable.elements)
otherwise unreachable;
if (this.hasSmis) {
TorqueMoveElementsSmi(elements, dst, src, length);
} else {
TorqueMoveElements(elements, dst, src, length);
}
}
}
const stable: JSArray;
unstable: FastJSArray;
const map: Map;
const hasDoubles: bool;
const hasSmis: bool;
arrayIsPushable: bool;
}
macro NewFastJSArrayWitness(array: FastJSArray): FastJSArrayWitness {
const kind = array.map.elements_kind;
return FastJSArrayWitness{
stable: array,
unstable: array,
map: array.map,
hasDoubles: IsDoubleElementsKind(kind),
hasSmis: IsElementsKindLessThanOrEqual(kind, HOLEY_SMI_ELEMENTS),
arrayIsPushable: false
};
}
struct FastJSArrayForReadWitness {
Get(): FastJSArrayForRead {
return this.unstable;
}
Recheck() labels CastError {
if (this.stable.map != this.map) goto CastError;
// We don't need to check elements kind or whether the prototype
// has changed away from the default JSArray prototype, because
// if the map remains the same then those properties hold.
//
// However, we have to make sure there are no elements in the
// prototype chain.
if (IsNoElementsProtectorCellInvalid()) goto CastError;
this.unstable = %RawDownCast<FastJSArrayForRead>(this.stable);
}
LoadElementNoHole(implicit context: Context)(k: Smi): JSAny
labels FoundHole {
if (this.hasDoubles) {
return LoadElementNoHole<FixedDoubleArray>(this.unstable, k)
otherwise FoundHole;
} else {
return LoadElementNoHole<FixedArray>(this.unstable, k)
otherwise FoundHole;
}
}
const stable: JSArray;
unstable: FastJSArrayForRead;
const map: Map;
const hasDoubles: bool;
}
macro NewFastJSArrayForReadWitness(array: FastJSArrayForRead):
FastJSArrayForReadWitness {
const kind = array.map.elements_kind;
return FastJSArrayForReadWitness{
stable: array,
unstable: array,
map: array.map,
hasDoubles: IsDoubleElementsKind(kind)
};
}
// Copyright 2019 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.
@generateCppClass
@abstract
extern class JSCollectionIterator extends JSObject {
// The backing hash table mapping keys to values.
table: Object;
// The index into the data table.
index: Object;
}
// Copyright 2019 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.
@abstract
@generateCppClass
extern class JSCollection extends JSObject {
// The backing hash table.
table: Object;
}
@generateCppClass
extern class JSSet extends JSCollection {
}
@generateCppClass
extern class JSMap extends JSCollection {
}
@abstract
@generateCppClass
extern class JSWeakCollection extends JSObject {
// The backing hash table mapping keys to values.
table: Object;
}
@generateCppClass
extern class JSWeakSet extends JSWeakCollection {
}
@generateCppClass
extern class JSWeakMap extends JSWeakCollection {
}
@abstract extern class JSMapIterator extends JSCollectionIterator;
extern class JSMapKeyIterator extends JSMapIterator
generates 'TNode<JSMapIterator>';
extern class JSMapKeyValueIterator extends JSMapIterator
generates 'TNode<JSMapIterator>';
extern class JSMapValueIterator extends JSMapIterator
generates 'TNode<JSMapIterator>';
@abstract extern class JSSetIterator extends JSCollectionIterator;
extern class JSSetKeyValueIterator extends JSSetIterator
generates 'TNode<JSSetIterator>';
extern class JSSetValueIterator extends JSSetIterator
generates 'TNode<JSSetIterator>';
// Copyright 2019 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.
@abstract
@dirtyInstantiatedAbstractClass
@generateCppClass
extern class JSGeneratorObject extends JSObject {
function: JSFunction;
context: Context;
receiver: JSAny;
// For executing generators: the most recent input value.
// For suspended generators: debug information (bytecode offset).
// There is currently no need to remember the most recent input value for a
// suspended generator.
input_or_debug_pos: Object;
resume_mode: Smi;
continuation: Smi;
// Saved interpreter register file.
parameters_and_registers: FixedArray;
}
@generateCppClass
extern class JSAsyncFunctionObject extends JSGeneratorObject {
promise: JSPromise;
}
@generateCppClass
extern class JSAsyncGeneratorObject extends JSGeneratorObject {
// Pointer to the head of a singly linked list of AsyncGeneratorRequest, or
// undefined.
queue: HeapObject;
is_awaiting: Smi;
}
@generateCppClass
extern class AsyncGeneratorRequest extends Struct {
next: AsyncGeneratorRequest|Undefined;
resume_mode: Smi;
value: Object;
promise: JSPromise;
}
This diff is collapsed.
// Copyright 2019 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.
// JSPromise constants
const kJSPromiseStatusMask: constexpr int31
generates 'JSPromise::kStatusMask';
const kJSPromiseStatusShift: constexpr int31
generates 'JSPromise::kStatusShift';
const kJSPromiseHasHandlerMask: constexpr int31
generates 'JSPromise::kHasHandlerMask';
@generateCppClass
extern class JSPromise extends JSObject {
Status(): PromiseState {
StaticAssert(kJSPromiseStatusShift == 0);
const status: int32 = Convert<int32>(this.flags) & kJSPromiseStatusMask;
return Convert<PromiseState>(status);
}
SetStatus(status: constexpr PromiseState): void {
assert(this.Status() == kPromisePending);
assert(status != kPromisePending);
const mask: Smi = SmiConstant(status);
this.flags = this.flags | mask;
}
HasHandler(): bool {
return (this.flags & kJSPromiseHasHandlerMask) != 0;
}
// Smi 0 terminated list of PromiseReaction objects in case the JSPromise was
// not settled yet, otherwise the result.
reactions_or_result: Zero|PromiseReaction|JSAny;
flags: Smi;
}
// Copyright 2019 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.
@generateCppClass
extern class JSProxy extends JSReceiver {
target: JSReceiver|Null;
handler: JSReceiver|Null;
}
// Just a starting shape for JSObject; properties can move after initialization.
@noVerifier
@hasSameInstanceTypeAsParent
extern class JSProxyRevocableResult extends JSObject {
proxy: JSAny;
revoke: JSAny;
}
macro NewJSProxyRevocableResult(implicit context: Context)(
proxy: JSProxy, revoke: JSFunction): JSProxyRevocableResult {
return new JSProxyRevocableResult{
map: GetProxyRevocableResultMap(),
properties_or_hash: kEmptyFixedArray,
elements: kEmptyFixedArray,
proxy,
revoke
};
}
// Copyright 2019 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.
@generateCppClass
extern class JSRegExpStringIterator extends JSObject {
// The [[IteratingRegExp]] internal property.
iterating_reg_exp: JSReceiver;
// The [[IteratedString]] internal property.
iterated_string: String;
flags: Smi;
}
This diff is collapsed.
This diff is collapsed.
// Copyright 2019 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.
@generateCppClass
extern class ArrayBoilerplateDescription extends Struct {
flags: Smi;
constant_elements: FixedArrayBase;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// Copyright 2019 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.
@generateCppClass
@apiExposedInstanceTypeValue(0x43)
@highestInstanceTypeWithinParentClassRange
extern class Oddball extends PrimitiveHeapObject {
to_number_raw: float64;
to_string: String;
to_number: Number;
type_of: String;
kind: Smi;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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