mirror of https://github.com/lukechilds/node.git
Browse Source
PR-URL: https://github.com/nodejs/node/pull/13263 Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: Myles Borins <myles.borins@gmail.com>v6
Michaël Zasso
8 years ago
1500 changed files with 110165 additions and 69314 deletions
File diff suppressed because it is too large
@ -1,58 +0,0 @@ |
|||
// 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.
|
|||
|
|||
/**
|
|||
* This header contains a set of experimental V8 APIs. We hope these will |
|||
* become a part of standard V8, but they may also be removed if we deem the |
|||
* experiment to not be successul. |
|||
*/ |
|||
#ifndef V8_INCLUDE_V8_EXPERIMENTAL_H_ |
|||
#define V8_INCLUDE_V8_EXPERIMENTAL_H_ |
|||
|
|||
#include "v8.h" // NOLINT(build/include) |
|||
|
|||
namespace v8 { |
|||
namespace experimental { |
|||
|
|||
// Allow the embedder to construct accessors that V8 can compile and use
|
|||
// directly, without jumping into the runtime.
|
|||
class V8_EXPORT FastAccessorBuilder { |
|||
public: |
|||
struct ValueId { |
|||
size_t value_id; |
|||
}; |
|||
struct LabelId { |
|||
size_t label_id; |
|||
}; |
|||
|
|||
static FastAccessorBuilder* New(Isolate* isolate); |
|||
|
|||
ValueId IntegerConstant(int int_constant); |
|||
ValueId GetReceiver(); |
|||
ValueId LoadInternalField(ValueId value_id, int field_no); |
|||
ValueId LoadInternalFieldUnchecked(ValueId value_id, int field_no); |
|||
ValueId LoadValue(ValueId value_id, int offset); |
|||
ValueId LoadObject(ValueId value_id, int offset); |
|||
ValueId ToSmi(ValueId value_id); |
|||
|
|||
void ReturnValue(ValueId value_id); |
|||
void CheckFlagSetOrReturnNull(ValueId value_id, int mask); |
|||
void CheckNotZeroOrReturnNull(ValueId value_id); |
|||
LabelId MakeLabel(); |
|||
void SetLabel(LabelId label_id); |
|||
void Goto(LabelId label_id); |
|||
void CheckNotZeroOrJump(ValueId value_id, LabelId label_id); |
|||
ValueId Call(v8::FunctionCallback callback, ValueId value_id); |
|||
|
|||
private: |
|||
FastAccessorBuilder() = delete; |
|||
FastAccessorBuilder(const FastAccessorBuilder&) = delete; |
|||
~FastAccessorBuilder() = delete; |
|||
void operator=(const FastAccessorBuilder&) = delete; |
|||
}; |
|||
|
|||
} // namespace experimental
|
|||
} // namespace v8
|
|||
|
|||
#endif // V8_INCLUDE_V8_EXPERIMENTAL_H_
|
File diff suppressed because it is too large
@ -1,4 +1,5 @@ |
|||
per-file i18n.*=cira@chromium.org |
|||
per-file i18n.*=mnita@google.com |
|||
per-file i18n.*=jshin@chromium.org |
|||
per-file typing-asm.*=aseemgarg@chromium.org |
|||
per-file typing-asm.*=bradnelson@chromium.org |
|||
|
@ -1,139 +0,0 @@ |
|||
// 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.
|
|||
|
|||
/**
|
|||
* Implementation for v8-experimental.h. |
|||
*/ |
|||
|
|||
#include "src/api-experimental.h" |
|||
|
|||
#include "include/v8-experimental.h" |
|||
#include "include/v8.h" |
|||
#include "src/api.h" |
|||
#include "src/fast-accessor-assembler.h" |
|||
#include "src/objects-inl.h" |
|||
|
|||
namespace { |
|||
|
|||
v8::internal::FastAccessorAssembler* FromApi( |
|||
v8::experimental::FastAccessorBuilder* builder) { |
|||
return reinterpret_cast<v8::internal::FastAccessorAssembler*>(builder); |
|||
} |
|||
|
|||
v8::experimental::FastAccessorBuilder* FromInternal( |
|||
v8::internal::FastAccessorAssembler* fast_accessor_assembler) { |
|||
return reinterpret_cast<v8::experimental::FastAccessorBuilder*>( |
|||
fast_accessor_assembler); |
|||
} |
|||
|
|||
} // namespace
|
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
namespace experimental { |
|||
|
|||
|
|||
MaybeHandle<Code> BuildCodeFromFastAccessorBuilder( |
|||
v8::experimental::FastAccessorBuilder* fast_handler) { |
|||
i::MaybeHandle<i::Code> code; |
|||
if (fast_handler != nullptr) { |
|||
auto faa = FromApi(fast_handler); |
|||
code = faa->Build(); |
|||
CHECK(!code.is_null()); |
|||
delete faa; |
|||
} |
|||
return code; |
|||
} |
|||
|
|||
} // namespace experimental
|
|||
} // namespace internal
|
|||
|
|||
|
|||
namespace experimental { |
|||
|
|||
|
|||
FastAccessorBuilder* FastAccessorBuilder::New(Isolate* isolate) { |
|||
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
|||
internal::FastAccessorAssembler* faa = |
|||
new internal::FastAccessorAssembler(i_isolate); |
|||
return FromInternal(faa); |
|||
} |
|||
|
|||
|
|||
FastAccessorBuilder::ValueId FastAccessorBuilder::IntegerConstant( |
|||
int const_value) { |
|||
return FromApi(this)->IntegerConstant(const_value); |
|||
} |
|||
|
|||
|
|||
FastAccessorBuilder::ValueId FastAccessorBuilder::GetReceiver() { |
|||
return FromApi(this)->GetReceiver(); |
|||
} |
|||
|
|||
|
|||
FastAccessorBuilder::ValueId FastAccessorBuilder::LoadInternalField( |
|||
ValueId value, int field_no) { |
|||
return FromApi(this)->LoadInternalField(value, field_no); |
|||
} |
|||
|
|||
FastAccessorBuilder::ValueId FastAccessorBuilder::LoadInternalFieldUnchecked( |
|||
ValueId value, int field_no) { |
|||
return FromApi(this)->LoadInternalFieldUnchecked(value, field_no); |
|||
} |
|||
|
|||
FastAccessorBuilder::ValueId FastAccessorBuilder::LoadValue(ValueId value_id, |
|||
int offset) { |
|||
return FromApi(this)->LoadValue(value_id, offset); |
|||
} |
|||
|
|||
|
|||
FastAccessorBuilder::ValueId FastAccessorBuilder::LoadObject(ValueId value_id, |
|||
int offset) { |
|||
return FromApi(this)->LoadObject(value_id, offset); |
|||
} |
|||
|
|||
FastAccessorBuilder::ValueId FastAccessorBuilder::ToSmi(ValueId value_id) { |
|||
return FromApi(this)->ToSmi(value_id); |
|||
} |
|||
|
|||
void FastAccessorBuilder::ReturnValue(ValueId value) { |
|||
FromApi(this)->ReturnValue(value); |
|||
} |
|||
|
|||
|
|||
void FastAccessorBuilder::CheckFlagSetOrReturnNull(ValueId value_id, int mask) { |
|||
FromApi(this)->CheckFlagSetOrReturnNull(value_id, mask); |
|||
} |
|||
|
|||
|
|||
void FastAccessorBuilder::CheckNotZeroOrReturnNull(ValueId value_id) { |
|||
FromApi(this)->CheckNotZeroOrReturnNull(value_id); |
|||
} |
|||
|
|||
|
|||
FastAccessorBuilder::LabelId FastAccessorBuilder::MakeLabel() { |
|||
return FromApi(this)->MakeLabel(); |
|||
} |
|||
|
|||
|
|||
void FastAccessorBuilder::SetLabel(LabelId label_id) { |
|||
FromApi(this)->SetLabel(label_id); |
|||
} |
|||
|
|||
void FastAccessorBuilder::Goto(LabelId label_id) { |
|||
FromApi(this)->Goto(label_id); |
|||
} |
|||
|
|||
void FastAccessorBuilder::CheckNotZeroOrJump(ValueId value_id, |
|||
LabelId label_id) { |
|||
FromApi(this)->CheckNotZeroOrJump(value_id, label_id); |
|||
} |
|||
|
|||
FastAccessorBuilder::ValueId FastAccessorBuilder::Call( |
|||
v8::FunctionCallback callback, ValueId value_id) { |
|||
return FromApi(this)->Call(callback, value_id); |
|||
} |
|||
|
|||
} // namespace experimental
|
|||
} // namespace v8
|
@ -1,28 +0,0 @@ |
|||
// 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.
|
|||
|
|||
#ifndef V8_API_EXPERIMENTAL_H_ |
|||
#define V8_API_EXPERIMENTAL_H_ |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
class Code; |
|||
template <typename T> |
|||
class MaybeHandle; |
|||
} // internal;
|
|||
namespace experimental { |
|||
class FastAccessorBuilder; |
|||
} // experimental
|
|||
|
|||
namespace internal { |
|||
namespace experimental { |
|||
|
|||
v8::internal::MaybeHandle<v8::internal::Code> BuildCodeFromFastAccessorBuilder( |
|||
v8::experimental::FastAccessorBuilder* fast_handler); |
|||
|
|||
} // namespace experimental
|
|||
} // namespace internal
|
|||
} // namespace v8
|
|||
|
|||
#endif // V8_API_EXPERIMENTAL_H_
|
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,110 @@ |
|||
// Copyright 2017 the V8 project authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#ifndef V8_ASMJS_ASM_NAMES_H_ |
|||
#define V8_ASMJS_ASM_NAMES_H_ |
|||
|
|||
#define STDLIB_MATH_VALUE_LIST(V) \ |
|||
V(E) \ |
|||
V(LN10) \ |
|||
V(LN2) \ |
|||
V(LOG2E) \ |
|||
V(LOG10E) \ |
|||
V(PI) \ |
|||
V(SQRT1_2) \ |
|||
V(SQRT2) |
|||
|
|||
// V(stdlib.Math.<name>, Name, wasm-opcode, asm-js-type)
|
|||
#define STDLIB_MATH_FUNCTION_MONOMORPHIC_LIST(V) \ |
|||
V(acos, Acos, kExprF64Acos, dq2d) \ |
|||
V(asin, Asin, kExprF64Asin, dq2d) \ |
|||
V(atan, Atan, kExprF64Atan, dq2d) \ |
|||
V(cos, Cos, kExprF64Cos, dq2d) \ |
|||
V(sin, Sin, kExprF64Sin, dq2d) \ |
|||
V(tan, Tan, kExprF64Tan, dq2d) \ |
|||
V(exp, Exp, kExprF64Exp, dq2d) \ |
|||
V(log, Log, kExprF64Log, dq2d) \ |
|||
V(atan2, Atan2, kExprF64Atan2, dqdq2d) \ |
|||
V(pow, Pow, kExprF64Pow, dqdq2d) \ |
|||
V(imul, Imul, kExprI32Mul, ii2s) \ |
|||
V(clz32, Clz32, kExprI32Clz, i2s) |
|||
|
|||
// V(stdlib.Math.<name>, Name, unused, asm-js-type)
|
|||
#define STDLIB_MATH_FUNCTION_CEIL_LIKE_LIST(V) \ |
|||
V(ceil, Ceil, x, ceil_like) \ |
|||
V(floor, Floor, x, ceil_like) \ |
|||
V(sqrt, Sqrt, x, ceil_like) |
|||
|
|||
// V(stdlib.Math.<name>, Name, unused, asm-js-type)
|
|||
#define STDLIB_MATH_FUNCTION_LIST(V) \ |
|||
V(min, Min, x, minmax) \ |
|||
V(max, Max, x, minmax) \ |
|||
V(abs, Abs, x, abs) \ |
|||
V(fround, Fround, x, fround) \ |
|||
STDLIB_MATH_FUNCTION_MONOMORPHIC_LIST(V) \ |
|||
STDLIB_MATH_FUNCTION_CEIL_LIKE_LIST(V) |
|||
|
|||
// V(stdlib.<name>, wasm-load-type, wasm-store-type, wasm-type)
|
|||
#define STDLIB_ARRAY_TYPE_LIST(V) \ |
|||
V(Int8Array, Mem8S, Mem8, I32) \ |
|||
V(Uint8Array, Mem8U, Mem8, I32) \ |
|||
V(Int16Array, Mem16S, Mem16, I32) \ |
|||
V(Uint16Array, Mem16U, Mem16, I32) \ |
|||
V(Int32Array, Mem, Mem, I32) \ |
|||
V(Uint32Array, Mem, Mem, I32) \ |
|||
V(Float32Array, Mem, Mem, F32) \ |
|||
V(Float64Array, Mem, Mem, F64) |
|||
|
|||
#define STDLIB_OTHER_LIST(V) \ |
|||
V(Infinity) \ |
|||
V(NaN) \ |
|||
V(Math) |
|||
|
|||
// clang-format off (for return)
|
|||
#define KEYWORD_NAME_LIST(V) \ |
|||
V(arguments) \ |
|||
V(break) \ |
|||
V(case) \ |
|||
V(const) \ |
|||
V(continue) \ |
|||
V(default) \ |
|||
V(do) \ |
|||
V(else) \ |
|||
V(eval) \ |
|||
V(for) \ |
|||
V(function) \ |
|||
V(if) \ |
|||
V(new) \ |
|||
V(return ) \ |
|||
V(switch) \ |
|||
V(var) \ |
|||
V(while) |
|||
// clang-format on
|
|||
|
|||
// V(token-string, token-name)
|
|||
#define LONG_SYMBOL_NAME_LIST(V) \ |
|||
V("<=", LE) \ |
|||
V(">=", GE) \ |
|||
V("==", EQ) \ |
|||
V("!=", NE) \ |
|||
V("<<", SHL) \ |
|||
V(">>", SAR) \ |
|||
V(">>>", SHR) \ |
|||
V("'use asm'", UseAsm) |
|||
|
|||
// clang-format off
|
|||
#define SIMPLE_SINGLE_TOKEN_LIST(V) \ |
|||
V('+') V('-') V('*') V('%') V('~') V('^') V('&') V('|') V('(') V(')') \ |
|||
V('[') V(']') V('{') V('}') V(':') V(';') V(',') V('?') |
|||
// clang-format on
|
|||
|
|||
// V(name, value, string-name)
|
|||
#define SPECIAL_TOKEN_LIST(V) \ |
|||
V(kUninitialized, 0, "{uninitalized}") \ |
|||
V(kEndOfInput, -1, "{end of input}") \ |
|||
V(kParseError, -2, "{parse error}") \ |
|||
V(kUnsigned, -3, "{unsigned value}") \ |
|||
V(kDouble, -4, "{double value}") |
|||
|
|||
#endif |
File diff suppressed because it is too large
@ -0,0 +1,316 @@ |
|||
// Copyright 2017 the V8 project authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#ifndef V8_ASMJS_ASM_PARSER_H_ |
|||
#define V8_ASMJS_ASM_PARSER_H_ |
|||
|
|||
#include <list> |
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
#include "src/asmjs/asm-scanner.h" |
|||
#include "src/asmjs/asm-typer.h" |
|||
#include "src/asmjs/asm-types.h" |
|||
#include "src/wasm/signature-map.h" |
|||
#include "src/wasm/wasm-module-builder.h" |
|||
#include "src/zone/zone-containers.h" |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
namespace wasm { |
|||
|
|||
// A custom parser + validator + wasm converter for asm.js:
|
|||
// http://asmjs.org/spec/latest/
|
|||
// This parser intentionally avoids the portion of JavaScript parsing
|
|||
// that are not required to determine if code is valid asm.js code.
|
|||
// * It is mostly one pass.
|
|||
// * It bails out on unexpected input.
|
|||
// * It assumes strict ordering insofar as permitted by asm.js validation rules.
|
|||
// * It relies on a custom scanner that provides de-duped identifiers in two
|
|||
// scopes (local + module wide).
|
|||
class AsmJsParser { |
|||
public: |
|||
explicit AsmJsParser(Isolate* isolate, Zone* zone, Handle<Script> script, |
|||
int start, int end); |
|||
bool Run(); |
|||
const char* failure_message() const { return failure_message_.c_str(); } |
|||
int failure_location() const { return failure_location_; } |
|||
WasmModuleBuilder* module_builder() { return module_builder_; } |
|||
const AsmTyper::StdlibSet* stdlib_uses() const { return &stdlib_uses_; } |
|||
|
|||
private: |
|||
// clang-format off
|
|||
enum class VarKind { |
|||
kUnused, |
|||
kLocal, |
|||
kGlobal, |
|||
kSpecial, |
|||
kFunction, |
|||
kTable, |
|||
kImportedFunction, |
|||
#define V(_unused0, Name, _unused1, _unused2) kMath##Name, |
|||
STDLIB_MATH_FUNCTION_LIST(V) |
|||
#undef V |
|||
#define V(Name) kMath##Name, |
|||
STDLIB_MATH_VALUE_LIST(V) |
|||
#undef V |
|||
}; |
|||
// clang-format on
|
|||
|
|||
struct FunctionImportInfo { |
|||
char* function_name; |
|||
size_t function_name_size; |
|||
SignatureMap cache; |
|||
std::vector<uint32_t> cache_index; |
|||
}; |
|||
|
|||
struct VarInfo { |
|||
AsmType* type; |
|||
WasmFunctionBuilder* function_builder; |
|||
FunctionImportInfo* import; |
|||
int32_t mask; |
|||
uint32_t index; |
|||
VarKind kind; |
|||
bool mutable_variable; |
|||
bool function_defined; |
|||
|
|||
VarInfo(); |
|||
void DeclareGlobalImport(AsmType* type, uint32_t index); |
|||
void DeclareStdlibFunc(VarKind kind, AsmType* type); |
|||
}; |
|||
|
|||
struct GlobalImport { |
|||
char* import_name; |
|||
size_t import_name_size; |
|||
uint32_t import_index; |
|||
uint32_t global_index; |
|||
bool needs_init; |
|||
}; |
|||
|
|||
enum class BlockKind { kRegular, kLoop, kOther }; |
|||
|
|||
struct BlockInfo { |
|||
BlockKind kind; |
|||
AsmJsScanner::token_t label; |
|||
}; |
|||
|
|||
// Helper class to make {TempVariable} safe for nesting.
|
|||
class TemporaryVariableScope; |
|||
|
|||
Zone* zone_; |
|||
AsmJsScanner scanner_; |
|||
WasmModuleBuilder* module_builder_; |
|||
WasmFunctionBuilder* current_function_builder_; |
|||
AsmType* return_type_; |
|||
std::uintptr_t stack_limit_; |
|||
AsmTyper::StdlibSet stdlib_uses_; |
|||
std::list<FunctionImportInfo> function_import_info_; |
|||
ZoneVector<VarInfo> global_var_info_; |
|||
ZoneVector<VarInfo> local_var_info_; |
|||
|
|||
int function_temp_locals_offset_; |
|||
int function_temp_locals_used_; |
|||
int function_temp_locals_depth_; |
|||
|
|||
// Error Handling related
|
|||
bool failed_; |
|||
std::string failure_message_; |
|||
int failure_location_; |
|||
|
|||
// Module Related.
|
|||
AsmJsScanner::token_t stdlib_name_; |
|||
AsmJsScanner::token_t foreign_name_; |
|||
AsmJsScanner::token_t heap_name_; |
|||
|
|||
static const AsmJsScanner::token_t kTokenNone = 0; |
|||
|
|||
// Track if parsing a heap assignment.
|
|||
bool inside_heap_assignment_; |
|||
AsmType* heap_access_type_; |
|||
|
|||
ZoneVector<BlockInfo> block_stack_; |
|||
|
|||
// Types used for stdlib function and their set up.
|
|||
AsmType* stdlib_dq2d_; |
|||
AsmType* stdlib_dqdq2d_; |
|||
AsmType* stdlib_fq2f_; |
|||
AsmType* stdlib_i2s_; |
|||
AsmType* stdlib_ii2s_; |
|||
AsmType* stdlib_minmax_; |
|||
AsmType* stdlib_abs_; |
|||
AsmType* stdlib_ceil_like_; |
|||
AsmType* stdlib_fround_; |
|||
|
|||
// When making calls, the return type is needed to lookup signatures.
|
|||
// For +callsite(..) or fround(callsite(..)) use this value to pass
|
|||
// along the coercion.
|
|||
AsmType* call_coercion_; |
|||
|
|||
// The source position associated with the above {call_coercion}.
|
|||
size_t call_coercion_position_; |
|||
|
|||
// Used to track the last label we've seen so it can be matched to later
|
|||
// statements it's attached to.
|
|||
AsmJsScanner::token_t pending_label_; |
|||
|
|||
// Global imports.
|
|||
// NOTE: Holds the strings referenced in wasm-module-builder for imports.
|
|||
ZoneLinkedList<GlobalImport> global_imports_; |
|||
|
|||
Zone* zone() { return zone_; } |
|||
|
|||
inline bool Peek(AsmJsScanner::token_t token) { |
|||
return scanner_.Token() == token; |
|||
} |
|||
|
|||
inline bool Check(AsmJsScanner::token_t token) { |
|||
if (scanner_.Token() == token) { |
|||
scanner_.Next(); |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
inline bool CheckForZero() { |
|||
if (scanner_.IsUnsigned() && scanner_.AsUnsigned() == 0) { |
|||
scanner_.Next(); |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
inline bool CheckForDouble(double* value) { |
|||
if (scanner_.IsDouble()) { |
|||
*value = scanner_.AsDouble(); |
|||
scanner_.Next(); |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
inline bool CheckForUnsigned(uint64_t* value) { |
|||
if (scanner_.IsUnsigned()) { |
|||
*value = scanner_.AsUnsigned(); |
|||
scanner_.Next(); |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
inline bool CheckForUnsignedBelow(uint64_t limit, uint64_t* value) { |
|||
if (scanner_.IsUnsigned() && scanner_.AsUnsigned() < limit) { |
|||
*value = scanner_.AsUnsigned(); |
|||
scanner_.Next(); |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
inline AsmJsScanner::token_t Consume() { |
|||
AsmJsScanner::token_t ret = scanner_.Token(); |
|||
scanner_.Next(); |
|||
return ret; |
|||
} |
|||
|
|||
void SkipSemicolon(); |
|||
|
|||
VarInfo* GetVarInfo(AsmJsScanner::token_t token); |
|||
uint32_t VarIndex(VarInfo* info); |
|||
void DeclareGlobal(VarInfo* info, bool mutable_variable, AsmType* type, |
|||
ValueType vtype, |
|||
const WasmInitExpr& init = WasmInitExpr()); |
|||
|
|||
// Allocates a temporary local variable. The given {index} is absolute within
|
|||
// the function body, consider using {TemporaryVariableScope} when nesting.
|
|||
uint32_t TempVariable(int index); |
|||
|
|||
void AddGlobalImport(std::string name, AsmType* type, ValueType vtype, |
|||
bool mutable_variable, VarInfo* info); |
|||
|
|||
// Use to set up block stack layers (including synthetic ones for if-else).
|
|||
// Begin/Loop/End below are implemented with these plus code generation.
|
|||
void BareBegin(BlockKind kind = BlockKind::kOther, |
|||
AsmJsScanner::token_t label = 0); |
|||
void BareEnd(); |
|||
int FindContinueLabelDepth(AsmJsScanner::token_t label); |
|||
int FindBreakLabelDepth(AsmJsScanner::token_t label); |
|||
|
|||
// Use to set up actual wasm blocks/loops.
|
|||
void Begin(AsmJsScanner::token_t label = 0); |
|||
void Loop(AsmJsScanner::token_t label = 0); |
|||
void End(); |
|||
|
|||
void InitializeStdlibTypes(); |
|||
|
|||
FunctionSig* ConvertSignature(AsmType* return_type, |
|||
const std::vector<AsmType*>& params); |
|||
|
|||
// 6.1 ValidateModule
|
|||
void ValidateModule(); |
|||
void ValidateModuleParameters(); |
|||
void ValidateModuleVars(); |
|||
void ValidateModuleVar(bool mutable_variable); |
|||
bool ValidateModuleVarImport(VarInfo* info, bool mutable_variable); |
|||
void ValidateModuleVarStdlib(VarInfo* info); |
|||
void ValidateModuleVarNewStdlib(VarInfo* info); |
|||
void ValidateModuleVarFromGlobal(VarInfo* info, bool mutable_variable); |
|||
|
|||
void ValidateExport(); // 6.2 ValidateExport
|
|||
void ValidateFunctionTable(); // 6.3 ValidateFunctionTable
|
|||
void ValidateFunction(); // 6.4 ValidateFunction
|
|||
void ValidateFunctionParams(std::vector<AsmType*>* params); |
|||
void ValidateFunctionLocals(size_t param_count, |
|||
std::vector<ValueType>* locals); |
|||
void ValidateStatement(); // ValidateStatement
|
|||
void Block(); // 6.5.1 Block
|
|||
void ExpressionStatement(); // 6.5.2 ExpressionStatement
|
|||
void EmptyStatement(); // 6.5.3 EmptyStatement
|
|||
void IfStatement(); // 6.5.4 IfStatement
|
|||
void ReturnStatement(); // 6.5.5 ReturnStatement
|
|||
bool IterationStatement(); // 6.5.6 IterationStatement
|
|||
void WhileStatement(); // 6.5.6 IterationStatement - while
|
|||
void DoStatement(); // 6.5.6 IterationStatement - do
|
|||
void ForStatement(); // 6.5.6 IterationStatement - for
|
|||
void BreakStatement(); // 6.5.7 BreakStatement
|
|||
void ContinueStatement(); // 6.5.8 ContinueStatement
|
|||
void LabelledStatement(); // 6.5.9 LabelledStatement
|
|||
void SwitchStatement(); // 6.5.10 SwitchStatement
|
|||
void ValidateCase(); // 6.6. ValidateCase
|
|||
void ValidateDefault(); // 6.7 ValidateDefault
|
|||
AsmType* ValidateExpression(); // 6.8 ValidateExpression
|
|||
AsmType* Expression(AsmType* expect); // 6.8.1 Expression
|
|||
AsmType* NumericLiteral(); // 6.8.2 NumericLiteral
|
|||
AsmType* Identifier(); // 6.8.3 Identifier
|
|||
AsmType* CallExpression(); // 6.8.4 CallExpression
|
|||
AsmType* MemberExpression(); // 6.8.5 MemberExpression
|
|||
AsmType* AssignmentExpression(); // 6.8.6 AssignmentExpression
|
|||
AsmType* UnaryExpression(); // 6.8.7 UnaryExpression
|
|||
AsmType* MultiplicativeExpression(); // 6.8.8 MultaplicativeExpression
|
|||
AsmType* AdditiveExpression(); // 6.8.9 AdditiveExpression
|
|||
AsmType* ShiftExpression(); // 6.8.10 ShiftExpression
|
|||
AsmType* RelationalExpression(); // 6.8.11 RelationalExpression
|
|||
AsmType* EqualityExpression(); // 6.8.12 EqualityExpression
|
|||
AsmType* BitwiseANDExpression(); // 6.8.13 BitwiseANDExpression
|
|||
AsmType* BitwiseXORExpression(); // 6.8.14 BitwiseXORExpression
|
|||
AsmType* BitwiseORExpression(); // 6.8.15 BitwiseORExpression
|
|||
AsmType* ConditionalExpression(); // 6.8.16 ConditionalExpression
|
|||
AsmType* ParenthesizedExpression(); // 6.8.17 ParenthesiedExpression
|
|||
AsmType* ValidateCall(); // 6.9 ValidateCall
|
|||
bool PeekCall(); // 6.9 ValidateCall - helper
|
|||
void ValidateHeapAccess(); // 6.10 ValidateHeapAccess
|
|||
void ValidateFloatCoercion(); // 6.11 ValidateFloatCoercion
|
|||
|
|||
void GatherCases(std::vector<int32_t>* cases); |
|||
}; |
|||
|
|||
} // namespace wasm
|
|||
} // namespace internal
|
|||
} // namespace v8
|
|||
|
|||
#endif // V8_ASMJS_ASM_PARSER_H_
|
@ -0,0 +1,431 @@ |
|||
// Copyright 2017 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/asmjs/asm-scanner.h" |
|||
|
|||
#include "src/conversions.h" |
|||
#include "src/flags.h" |
|||
#include "src/parsing/scanner.h" |
|||
#include "src/unicode-cache.h" |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
|
|||
namespace { |
|||
// Cap number of identifiers to ensure we can assign both global and
|
|||
// local ones a token id in the range of an int32_t.
|
|||
static const int kMaxIdentifierCount = 0xf000000; |
|||
}; |
|||
|
|||
AsmJsScanner::AsmJsScanner() |
|||
: token_(kUninitialized), |
|||
preceding_token_(kUninitialized), |
|||
next_token_(kUninitialized), |
|||
position_(0), |
|||
preceding_position_(0), |
|||
next_position_(0), |
|||
rewind_(false), |
|||
in_local_scope_(false), |
|||
global_count_(0), |
|||
double_value_(0.0), |
|||
unsigned_value_(0), |
|||
preceded_by_newline_(false) { |
|||
#define V(name, _junk1, _junk2, _junk3) property_names_[#name] = kToken_##name; |
|||
STDLIB_MATH_FUNCTION_LIST(V) |
|||
STDLIB_ARRAY_TYPE_LIST(V) |
|||
#undef V |
|||
#define V(name) property_names_[#name] = kToken_##name; |
|||
STDLIB_MATH_VALUE_LIST(V) |
|||
STDLIB_OTHER_LIST(V) |
|||
#undef V |
|||
#define V(name) global_names_[#name] = kToken_##name; |
|||
KEYWORD_NAME_LIST(V) |
|||
#undef V |
|||
} |
|||
|
|||
void AsmJsScanner::SetStream(std::unique_ptr<Utf16CharacterStream> stream) { |
|||
stream_ = std::move(stream); |
|||
Next(); |
|||
} |
|||
|
|||
void AsmJsScanner::Next() { |
|||
if (rewind_) { |
|||
preceding_token_ = token_; |
|||
preceding_position_ = position_; |
|||
token_ = next_token_; |
|||
position_ = next_position_; |
|||
next_token_ = kUninitialized; |
|||
next_position_ = 0; |
|||
rewind_ = false; |
|||
return; |
|||
} |
|||
|
|||
if (token_ == kEndOfInput || token_ == kParseError) { |
|||
return; |
|||
} |
|||
|
|||
#if DEBUG |
|||
if (FLAG_trace_asm_scanner) { |
|||
if (Token() == kDouble) { |
|||
PrintF("%lf ", AsDouble()); |
|||
} else if (Token() == kUnsigned) { |
|||
PrintF("%" PRIu64 " ", AsUnsigned()); |
|||
} else { |
|||
std::string name = Name(Token()); |
|||
PrintF("%s ", name.c_str()); |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
preceded_by_newline_ = false; |
|||
preceding_token_ = token_; |
|||
preceding_position_ = position_; |
|||
|
|||
for (;;) { |
|||
position_ = stream_->pos(); |
|||
uc32 ch = stream_->Advance(); |
|||
switch (ch) { |
|||
case ' ': |
|||
case '\t': |
|||
case '\r': |
|||
// Ignore whitespace.
|
|||
break; |
|||
|
|||
case '\n': |
|||
// Track when we've passed a newline for optional semicolon support,
|
|||
// but keep scanning.
|
|||
preceded_by_newline_ = true; |
|||
break; |
|||
|
|||
case kEndOfInput: |
|||
token_ = kEndOfInput; |
|||
return; |
|||
|
|||
case '\'': |
|||
case '"': |
|||
ConsumeString(ch); |
|||
return; |
|||
|
|||
case '/': |
|||
ch = stream_->Advance(); |
|||
if (ch == '/') { |
|||
ConsumeCPPComment(); |
|||
} else if (ch == '*') { |
|||
if (!ConsumeCComment()) { |
|||
token_ = kParseError; |
|||
return; |
|||
} |
|||
} else { |
|||
stream_->Back(); |
|||
token_ = '/'; |
|||
return; |
|||
} |
|||
// Breaks out of switch, but loops again (i.e. the case when we parsed
|
|||
// a comment, but need to continue to look for the next token).
|
|||
break; |
|||
|
|||
case '<': |
|||
case '>': |
|||
case '=': |
|||
case '!': |
|||
ConsumeCompareOrShift(ch); |
|||
return; |
|||
|
|||
#define V(single_char_token) case single_char_token: |
|||
SIMPLE_SINGLE_TOKEN_LIST(V) |
|||
#undef V |
|||
// Use fixed token IDs for ASCII.
|
|||
token_ = ch; |
|||
return; |
|||
|
|||
default: |
|||
if (IsIdentifierStart(ch)) { |
|||
ConsumeIdentifier(ch); |
|||
} else if (IsNumberStart(ch)) { |
|||
ConsumeNumber(ch); |
|||
} else { |
|||
// TODO(bradnelson): Support unicode (probably via UnicodeCache).
|
|||
token_ = kParseError; |
|||
} |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void AsmJsScanner::Rewind() { |
|||
DCHECK_NE(kUninitialized, preceding_token_); |
|||
// TODO(bradnelson): Currently rewinding needs to leave in place the
|
|||
// preceding newline state (in case a |0 ends a line).
|
|||
// This is weird and stateful, fix me.
|
|||
DCHECK(!rewind_); |
|||
next_token_ = token_; |
|||
next_position_ = position_; |
|||
token_ = preceding_token_; |
|||
position_ = preceding_position_; |
|||
preceding_token_ = kUninitialized; |
|||
preceding_position_ = 0; |
|||
rewind_ = true; |
|||
identifier_string_.clear(); |
|||
} |
|||
|
|||
void AsmJsScanner::ResetLocals() { local_names_.clear(); } |
|||
|
|||
#if DEBUG |
|||
// Only used for debugging.
|
|||
std::string AsmJsScanner::Name(token_t token) const { |
|||
if (token >= 32 && token < 127) { |
|||
return std::string(1, static_cast<char>(token)); |
|||
} |
|||
for (auto& i : local_names_) { |
|||
if (i.second == token) { |
|||
return i.first; |
|||
} |
|||
} |
|||
for (auto& i : global_names_) { |
|||
if (i.second == token) { |
|||
return i.first; |
|||
} |
|||
} |
|||
for (auto& i : property_names_) { |
|||
if (i.second == token) { |
|||
return i.first; |
|||
} |
|||
} |
|||
switch (token) { |
|||
#define V(rawname, name) \ |
|||
case kToken_##name: \ |
|||
return rawname; |
|||
LONG_SYMBOL_NAME_LIST(V) |
|||
#undef V |
|||
#define V(name, value, string_name) \ |
|||
case name: \ |
|||
return string_name; |
|||
SPECIAL_TOKEN_LIST(V) |
|||
default: |
|||
break; |
|||
} |
|||
UNREACHABLE(); |
|||
return "{unreachable}"; |
|||
} |
|||
#endif |
|||
|
|||
int AsmJsScanner::GetPosition() const { |
|||
DCHECK(!rewind_); |
|||
return static_cast<int>(stream_->pos()); |
|||
} |
|||
|
|||
void AsmJsScanner::Seek(int pos) { |
|||
stream_->Seek(pos); |
|||
preceding_token_ = kUninitialized; |
|||
token_ = kUninitialized; |
|||
next_token_ = kUninitialized; |
|||
preceding_position_ = 0; |
|||
position_ = 0; |
|||
next_position_ = 0; |
|||
rewind_ = false; |
|||
Next(); |
|||
} |
|||
|
|||
void AsmJsScanner::ConsumeIdentifier(uc32 ch) { |
|||
// Consume characters while still part of the identifier.
|
|||
identifier_string_.clear(); |
|||
while (IsIdentifierPart(ch)) { |
|||
identifier_string_ += ch; |
|||
ch = stream_->Advance(); |
|||
} |
|||
// Go back one for next time.
|
|||
stream_->Back(); |
|||
|
|||
// Decode what the identifier means.
|
|||
if (preceding_token_ == '.') { |
|||
auto i = property_names_.find(identifier_string_); |
|||
if (i != property_names_.end()) { |
|||
token_ = i->second; |
|||
return; |
|||
} |
|||
} else { |
|||
{ |
|||
auto i = local_names_.find(identifier_string_); |
|||
if (i != local_names_.end()) { |
|||
token_ = i->second; |
|||
return; |
|||
} |
|||
} |
|||
if (!in_local_scope_) { |
|||
auto i = global_names_.find(identifier_string_); |
|||
if (i != global_names_.end()) { |
|||
token_ = i->second; |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
if (preceding_token_ == '.') { |
|||
CHECK(global_count_ < kMaxIdentifierCount); |
|||
token_ = kGlobalsStart + global_count_++; |
|||
property_names_[identifier_string_] = token_; |
|||
} else if (in_local_scope_) { |
|||
CHECK(local_names_.size() < kMaxIdentifierCount); |
|||
token_ = kLocalsStart - static_cast<token_t>(local_names_.size()); |
|||
local_names_[identifier_string_] = token_; |
|||
} else { |
|||
CHECK(global_count_ < kMaxIdentifierCount); |
|||
token_ = kGlobalsStart + global_count_++; |
|||
global_names_[identifier_string_] = token_; |
|||
} |
|||
} |
|||
|
|||
void AsmJsScanner::ConsumeNumber(uc32 ch) { |
|||
std::string number; |
|||
number = ch; |
|||
bool has_dot = ch == '.'; |
|||
for (;;) { |
|||
ch = stream_->Advance(); |
|||
if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || |
|||
(ch >= 'A' && ch <= 'F') || ch == '.' || ch == 'b' || ch == 'o' || |
|||
ch == 'x' || |
|||
((ch == '-' || ch == '+') && (number[number.size() - 1] == 'e' || |
|||
number[number.size() - 1] == 'E'))) { |
|||
// TODO(bradnelson): Test weird cases ending in -.
|
|||
if (ch == '.') { |
|||
has_dot = true; |
|||
} |
|||
number.push_back(ch); |
|||
} else { |
|||
break; |
|||
} |
|||
} |
|||
stream_->Back(); |
|||
// Special case the most common number.
|
|||
if (number.size() == 1 && number[0] == '0') { |
|||
unsigned_value_ = 0; |
|||
token_ = kUnsigned; |
|||
return; |
|||
} |
|||
// Pick out dot.
|
|||
if (number.size() == 1 && number[0] == '.') { |
|||
token_ = '.'; |
|||
return; |
|||
} |
|||
// Decode numbers.
|
|||
UnicodeCache cache; |
|||
double_value_ = StringToDouble( |
|||
&cache, |
|||
Vector<uint8_t>( |
|||
const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(number.data())), |
|||
static_cast<int>(number.size())), |
|||
ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY | ALLOW_IMPLICIT_OCTAL); |
|||
if (std::isnan(double_value_)) { |
|||
// Check if string to number conversion didn't consume all the characters.
|
|||
// This happens if the character filter let through something invalid
|
|||
// like: 0123ef for example.
|
|||
// TODO(bradnelson): Check if this happens often enough to be a perf
|
|||
// problem.
|
|||
if (number[0] == '.') { |
|||
for (size_t k = 1; k < number.size(); ++k) { |
|||
stream_->Back(); |
|||
} |
|||
token_ = '.'; |
|||
return; |
|||
} |
|||
// Anything else that doesn't parse is an error.
|
|||
token_ = kParseError; |
|||
return; |
|||
} |
|||
if (has_dot) { |
|||
token_ = kDouble; |
|||
} else { |
|||
unsigned_value_ = static_cast<uint32_t>(double_value_); |
|||
token_ = kUnsigned; |
|||
} |
|||
} |
|||
|
|||
bool AsmJsScanner::ConsumeCComment() { |
|||
for (;;) { |
|||
uc32 ch = stream_->Advance(); |
|||
while (ch == '*') { |
|||
ch = stream_->Advance(); |
|||
if (ch == '/') { |
|||
return true; |
|||
} |
|||
} |
|||
if (ch == kEndOfInput) { |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void AsmJsScanner::ConsumeCPPComment() { |
|||
for (;;) { |
|||
uc32 ch = stream_->Advance(); |
|||
if (ch == '\n' || ch == kEndOfInput) { |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void AsmJsScanner::ConsumeString(uc32 quote) { |
|||
// Only string allowed is 'use asm' / "use asm".
|
|||
const char* expected = "use asm"; |
|||
for (; *expected != '\0'; ++expected) { |
|||
if (stream_->Advance() != *expected) { |
|||
token_ = kParseError; |
|||
return; |
|||
} |
|||
} |
|||
if (stream_->Advance() != quote) { |
|||
token_ = kParseError; |
|||
return; |
|||
} |
|||
token_ = kToken_UseAsm; |
|||
} |
|||
|
|||
void AsmJsScanner::ConsumeCompareOrShift(uc32 ch) { |
|||
uc32 next_ch = stream_->Advance(); |
|||
if (next_ch == '=') { |
|||
switch (ch) { |
|||
case '<': |
|||
token_ = kToken_LE; |
|||
break; |
|||
case '>': |
|||
token_ = kToken_GE; |
|||
break; |
|||
case '=': |
|||
token_ = kToken_EQ; |
|||
break; |
|||
case '!': |
|||
token_ = kToken_NE; |
|||
break; |
|||
default: |
|||
UNREACHABLE(); |
|||
} |
|||
} else if (ch == '<' && next_ch == '<') { |
|||
token_ = kToken_SHL; |
|||
} else if (ch == '>' && next_ch == '>') { |
|||
if (stream_->Advance() == '>') { |
|||
token_ = kToken_SHR; |
|||
} else { |
|||
token_ = kToken_SAR; |
|||
stream_->Back(); |
|||
} |
|||
} else { |
|||
stream_->Back(); |
|||
token_ = ch; |
|||
} |
|||
} |
|||
|
|||
bool AsmJsScanner::IsIdentifierStart(uc32 ch) { |
|||
return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_' || |
|||
ch == '$'; |
|||
} |
|||
|
|||
bool AsmJsScanner::IsIdentifierPart(uc32 ch) { |
|||
return IsIdentifierStart(ch) || (ch >= '0' && ch <= '9'); |
|||
} |
|||
|
|||
bool AsmJsScanner::IsNumberStart(uc32 ch) { |
|||
return ch == '.' || (ch >= '0' && ch <= '9'); |
|||
} |
|||
|
|||
} // namespace internal
|
|||
} // namespace v8
|
@ -0,0 +1,165 @@ |
|||
// Copyright 2017 the V8 project authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#ifndef V8_ASMJS_ASM_SCANNER_H_ |
|||
#define V8_ASMJS_ASM_SCANNER_H_ |
|||
|
|||
#include <memory> |
|||
#include <string> |
|||
#include <unordered_map> |
|||
|
|||
#include "src/asmjs/asm-names.h" |
|||
#include "src/base/logging.h" |
|||
#include "src/globals.h" |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
|
|||
class Utf16CharacterStream; |
|||
|
|||
// A custom scanner to extract the token stream needed to parse valid
|
|||
// asm.js: http://asmjs.org/spec/latest/
|
|||
// This scanner intentionally avoids the portion of JavaScript lexing
|
|||
// that are not required to determine if code is valid asm.js code.
|
|||
// * Strings are disallowed except for 'use asm'.
|
|||
// * Only the subset of keywords needed to check asm.js invariants are
|
|||
// included.
|
|||
// * Identifiers are accumulated into local + global string tables
|
|||
// (for performance).
|
|||
class V8_EXPORT_PRIVATE AsmJsScanner { |
|||
public: |
|||
typedef int32_t token_t; |
|||
|
|||
AsmJsScanner(); |
|||
// Pick the stream to parse (must be called before anything else).
|
|||
void SetStream(std::unique_ptr<Utf16CharacterStream> stream); |
|||
|
|||
// Get current token.
|
|||
token_t Token() const { return token_; } |
|||
// Get position of current token.
|
|||
size_t Position() const { return position_; } |
|||
// Advance to the next token.
|
|||
void Next(); |
|||
// Back up by one token.
|
|||
void Rewind(); |
|||
// Get raw string for current identifier.
|
|||
const std::string& GetIdentifierString() const { |
|||
// Identifier strings don't work after a rewind.
|
|||
DCHECK(!rewind_); |
|||
return identifier_string_; |
|||
} |
|||
// Check if we just passed a newline.
|
|||
bool IsPrecededByNewline() const { |
|||
// Newline tracking doesn't work if you back up.
|
|||
DCHECK(!rewind_); |
|||
return preceded_by_newline_; |
|||
} |
|||
|
|||
#if DEBUG |
|||
// Debug only method to go from a token back to its name.
|
|||
// Slow, only use for debugging.
|
|||
std::string Name(token_t token) const; |
|||
#endif |
|||
|
|||
// Get current position (to use with Seek).
|
|||
int GetPosition() const; |
|||
// Restores old position (token after that position).
|
|||
void Seek(int pos); |
|||
|
|||
// Select whether identifiers are resolved in global or local scope,
|
|||
// and which scope new identifiers are added to.
|
|||
void EnterLocalScope() { in_local_scope_ = true; } |
|||
void EnterGlobalScope() { in_local_scope_ = false; } |
|||
// Drop all current local identifiers.
|
|||
void ResetLocals(); |
|||
|
|||
// Methods to check if a token is an identifier and which scope.
|
|||
bool IsLocal() const { return IsLocal(Token()); } |
|||
bool IsGlobal() const { return IsGlobal(Token()); } |
|||
static bool IsLocal(token_t token) { return token <= kLocalsStart; } |
|||
static bool IsGlobal(token_t token) { return token >= kGlobalsStart; } |
|||
// Methods to find the index position of an identifier (count starting from
|
|||
// 0 for each scope separately).
|
|||
static size_t LocalIndex(token_t token) { |
|||
DCHECK(IsLocal(token)); |
|||
return -(token - kLocalsStart); |
|||
} |
|||
static size_t GlobalIndex(token_t token) { |
|||
DCHECK(IsGlobal(token)); |
|||
return token - kGlobalsStart; |
|||
} |
|||
|
|||
// Methods to check if the current token is an asm.js "number" (contains a
|
|||
// dot) or an "unsigned" (a number without a dot).
|
|||
bool IsUnsigned() const { return Token() == kUnsigned; } |
|||
uint64_t AsUnsigned() const { return unsigned_value_; } |
|||
bool IsDouble() const { return Token() == kDouble; } |
|||
double AsDouble() const { return double_value_; } |
|||
|
|||
// clang-format off
|
|||
enum { |
|||
// [-10000-kMaxIdentifierCount, -10000) :: Local identifiers (counting
|
|||
// backwards)
|
|||
// [-10000 .. -1) :: Builtin tokens like keywords
|
|||
// (also includes some special
|
|||
// ones like end of input)
|
|||
// 0 .. 255 :: Single char tokens
|
|||
// 256 .. 256+kMaxIdentifierCount :: Global identifiers
|
|||
kLocalsStart = -10000, |
|||
#define V(name, _junk1, _junk2, _junk3) kToken_##name, |
|||
STDLIB_MATH_FUNCTION_LIST(V) |
|||
STDLIB_ARRAY_TYPE_LIST(V) |
|||
#undef V |
|||
#define V(name) kToken_##name, |
|||
STDLIB_OTHER_LIST(V) |
|||
STDLIB_MATH_VALUE_LIST(V) |
|||
KEYWORD_NAME_LIST(V) |
|||
#undef V |
|||
#define V(rawname, name) kToken_##name, |
|||
LONG_SYMBOL_NAME_LIST(V) |
|||
#undef V |
|||
#define V(name, value, string_name) name = value, |
|||
SPECIAL_TOKEN_LIST(V) |
|||
#undef V |
|||
kGlobalsStart = 256, |
|||
}; |
|||
// clang-format on
|
|||
|
|||
private: |
|||
std::unique_ptr<Utf16CharacterStream> stream_; |
|||
token_t token_; |
|||
token_t preceding_token_; |
|||
token_t next_token_; // Only set when in {rewind} state.
|
|||
size_t position_; // Corresponds to {token} position.
|
|||
size_t preceding_position_; // Corresponds to {preceding_token} position.
|
|||
size_t next_position_; // Only set when in {rewind} state.
|
|||
bool rewind_; |
|||
std::string identifier_string_; |
|||
bool in_local_scope_; |
|||
std::unordered_map<std::string, token_t> local_names_; |
|||
std::unordered_map<std::string, token_t> global_names_; |
|||
std::unordered_map<std::string, token_t> property_names_; |
|||
int global_count_; |
|||
double double_value_; |
|||
uint64_t unsigned_value_; |
|||
bool preceded_by_newline_; |
|||
|
|||
// Consume multiple characters.
|
|||
void ConsumeIdentifier(uc32 ch); |
|||
void ConsumeNumber(uc32 ch); |
|||
bool ConsumeCComment(); |
|||
void ConsumeCPPComment(); |
|||
void ConsumeString(uc32 quote); |
|||
void ConsumeCompareOrShift(uc32 ch); |
|||
|
|||
// Classify character categories.
|
|||
bool IsIdentifierStart(uc32 ch); |
|||
bool IsIdentifierPart(uc32 ch); |
|||
bool IsNumberStart(uc32 ch); |
|||
}; |
|||
|
|||
} // namespace internal
|
|||
} // namespace v8
|
|||
|
|||
#endif // V8_ASMJS_ASM_SCANNER_H_
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue