Speedup some compiler routines (#441)

This commit is contained in:
Max Graey 2019-02-22 15:03:33 +02:00 committed by Daniel Wirtz
parent cc5522d6cc
commit 65c799c925
6 changed files with 139 additions and 130 deletions

View File

@ -451,14 +451,11 @@ export function compileCall(
arg0 = compiler.compileExpression(operands[0], Type.i32, ConversionKind.NONE, WrapMode.WRAP);
}
switch (compiler.currentType.kind) {
case TypeKind.I8:
case TypeKind.I16:
case TypeKind.U8:
case TypeKind.U16: {
ret = module.createUnary(UnaryOp.ClzI32, arg0);
break;
}
case TypeKind.BOOL: // usually overflows
case TypeKind.I8:
case TypeKind.U8:
case TypeKind.I16:
case TypeKind.U16:
case TypeKind.I32:
case TypeKind.U32: {
ret = module.createUnary(UnaryOp.ClzI32, arg0);
@ -531,14 +528,11 @@ export function compileCall(
arg0 = compiler.compileExpression(operands[0], Type.i32, ConversionKind.NONE, WrapMode.WRAP);
}
switch (compiler.currentType.kind) {
case TypeKind.I8:
case TypeKind.I16:
case TypeKind.U8:
case TypeKind.U16: {
ret = module.createUnary(UnaryOp.CtzI32, arg0);
break;
}
case TypeKind.BOOL: // usually overflows
case TypeKind.I8:
case TypeKind.U8:
case TypeKind.I16:
case TypeKind.U16:
case TypeKind.I32:
case TypeKind.U32: {
ret = module.createUnary(UnaryOp.CtzI32, arg0);
@ -611,14 +605,11 @@ export function compileCall(
arg0 = compiler.compileExpression(operands[0], Type.i32, ConversionKind.NONE, WrapMode.WRAP);
}
switch (compiler.currentType.kind) {
case TypeKind.I8:
case TypeKind.I16:
case TypeKind.U8:
case TypeKind.U16: {
ret = module.createUnary(UnaryOp.PopcntI32, arg0);
break;
}
case TypeKind.BOOL: // usually overflows
case TypeKind.I8:
case TypeKind.U8:
case TypeKind.I16:
case TypeKind.U16:
case TypeKind.I32:
case TypeKind.U32: {
ret = module.createUnary(UnaryOp.PopcntI32, arg0);
@ -2525,11 +2516,8 @@ export function compileCall(
case TypeKind.I16:
case TypeKind.U8:
case TypeKind.U16:
case TypeKind.BOOL: {
ret = module.createSelect(arg0, arg1, arg2);
break;
}
default: { // any other value type
case TypeKind.BOOL:
default: {
ret = module.createSelect(arg0, arg1, arg2);
break;
}

View File

@ -4499,7 +4499,6 @@ export class Compiler extends DiagnosticEmitter {
// simplify if cloning left without side effects is possible
if (expr = module.cloneExpression(leftExpr, true, 0)) {
this.makeIsTrueish(leftExpr, this.currentType);
expr = module.createIf(
this.makeIsTrueish(leftExpr, this.currentType),
rightExpr,
@ -6420,14 +6419,16 @@ export class Compiler extends DiagnosticEmitter {
var arrayOffset = arraySegment.offset;
if (hasGC) arrayOffset = i64_add(arrayOffset, i64_new(gcHeaderSize));
this.currentType = arrayInstance.type;
var buffer_offset = pos + arrayInstance.offsetof("buffer_");
var length_offset = pos + arrayInstance.offsetof("length_");
if (usizeTypeSize == 8) {
writeI64(bufferOffset, buf, pos + arrayInstance.offsetof("buffer_"));
writeI32(length, buf, pos + arrayInstance.offsetof("length_"));
writeI64(bufferOffset, buf, buffer_offset);
writeI32(length, buf, length_offset);
return this.module.createI64(i64_low(arrayOffset), i64_high(arrayOffset));
} else {
assert(i64_is_u32(bufferOffset));
writeI32(i64_low(bufferOffset), buf, pos + arrayInstance.offsetof("buffer_"));
writeI32(length, buf, pos + arrayInstance.offsetof("length_"));
writeI32(i64_low(bufferOffset), buf, buffer_offset);
writeI32(length, buf, length_offset);
assert(i64_is_u32(arrayOffset));
return this.module.createI32(i64_low(arrayOffset));
}
@ -6448,12 +6449,13 @@ export class Compiler extends DiagnosticEmitter {
var nativeElementType = elementType.toNativeType();
var isStatic = true;
for (let i = 0; i < length; ++i) {
let expr = expressions[i]
? this.compileExpression(<Expression>expressions[i], elementType, ConversionKind.IMPLICIT, WrapMode.NONE)
let expression = expressions[i];
let expr = expression
? this.compileExpression(<Expression>expression, elementType, ConversionKind.IMPLICIT, WrapMode.NONE)
: elementType.toNativeZero(module);
compiledValues[i] = expr;
if (isStatic) {
expr = module.precomputeExpression(compiledValues[i]);
expr = module.precomputeExpression(expr);
if (getExpressionId(expr) == ExpressionId.Const) {
assert(getExpressionType(expr) == nativeElementType);
constantValues[i] = expr;

View File

@ -1614,33 +1614,34 @@ export class Program extends DiagnosticEmitter {
element = assert(parent.lookupInSelf(name)); // possibly merged
var members = declaration.members;
for (let i = 0, k = members.length; i < k; ++i) {
switch (members[i].kind) {
let member = members[i];
switch (member.kind) {
case NodeKind.CLASSDECLARATION: {
this.initializeClass(<ClassDeclaration>members[i], element, queuedExtends, queuedImplements);
this.initializeClass(<ClassDeclaration>member, element, queuedExtends, queuedImplements);
break;
}
case NodeKind.ENUMDECLARATION: {
this.initializeEnum(<EnumDeclaration>members[i], element);
this.initializeEnum(<EnumDeclaration>member, element);
break;
}
case NodeKind.FUNCTIONDECLARATION: {
this.initializeFunction(<FunctionDeclaration>members[i], element);
this.initializeFunction(<FunctionDeclaration>member, element);
break;
}
case NodeKind.INTERFACEDECLARATION: {
this.initializeInterface(<InterfaceDeclaration>members[i], element);
this.initializeInterface(<InterfaceDeclaration>member, element);
break;
}
case NodeKind.NAMESPACEDECLARATION: {
this.initializeNamespace(<NamespaceDeclaration>members[i], element, queuedExtends, queuedImplements);
this.initializeNamespace(<NamespaceDeclaration>member, element, queuedExtends, queuedImplements);
break;
}
case NodeKind.TYPEDECLARATION: {
this.initializeTypeDefinition(<TypeDeclaration>members[i], element);
this.initializeTypeDefinition(<TypeDeclaration>member, element);
break;
}
case NodeKind.VARIABLE: {
this.initializeVariables(<VariableStatement>members[i], element);
this.initializeVariables(<VariableStatement>member, element);
break;
}
default: assert(false); // namespace member expected

View File

@ -500,6 +500,7 @@ export class Tokenizer extends DiagnosticEmitter {
/** Constructs a new tokenizer. */
constructor(source: Source, diagnostics: DiagnosticMessage[] | null = null) {
super(diagnostics);
this.source = source;
this.pos = 0;
this.end = source.text.length;
@ -598,11 +599,12 @@ export class Tokenizer extends DiagnosticEmitter {
case CharCode.AMPERSAND: {
++this.pos;
if (maxTokenLength > 1 && this.pos < this.end) {
if (text.charCodeAt(this.pos) == CharCode.AMPERSAND) {
let chr = text.charCodeAt(this.pos);
if (chr == CharCode.AMPERSAND) {
++this.pos;
return Token.AMPERSAND_AMPERSAND;
}
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
if (chr == CharCode.EQUALS) {
++this.pos;
return Token.AMPERSAND_EQUALS;
}
@ -620,11 +622,12 @@ export class Tokenizer extends DiagnosticEmitter {
case CharCode.ASTERISK: {
++this.pos;
if (maxTokenLength > 1 && this.pos < this.end) {
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
let chr = text.charCodeAt(this.pos);
if (chr == CharCode.EQUALS) {
++this.pos;
return Token.ASTERISK_EQUALS;
}
if (text.charCodeAt(this.pos) == CharCode.ASTERISK) {
if (chr == CharCode.ASTERISK) {
++this.pos;
if (
maxTokenLength > 2 && this.pos < this.end &&
@ -641,11 +644,12 @@ export class Tokenizer extends DiagnosticEmitter {
case CharCode.PLUS: {
++this.pos;
if (maxTokenLength > 1 && this.pos < this.end) {
if (text.charCodeAt(this.pos) == CharCode.PLUS) {
let chr = text.charCodeAt(this.pos);
if (chr == CharCode.PLUS) {
++this.pos;
return Token.PLUS_PLUS;
}
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
if (chr == CharCode.EQUALS) {
++this.pos;
return Token.PLUS_EQUALS;
}
@ -659,11 +663,12 @@ export class Tokenizer extends DiagnosticEmitter {
case CharCode.MINUS: {
++this.pos;
if (maxTokenLength > 1 && this.pos < this.end) {
if (text.charCodeAt(this.pos) == CharCode.MINUS) {
let chr = text.charCodeAt(this.pos);
if (chr == CharCode.MINUS) {
++this.pos;
return Token.MINUS_MINUS;
}
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
if (chr == CharCode.EQUALS) {
++this.pos;
return Token.MINUS_EQUALS;
}
@ -673,13 +678,14 @@ export class Tokenizer extends DiagnosticEmitter {
case CharCode.DOT: {
++this.pos;
if (maxTokenLength > 1 && this.pos < this.end) {
if (isDecimalDigit(text.charCodeAt(this.pos))) {
let chr = text.charCodeAt(this.pos);
if (isDecimalDigit(chr)) {
--this.pos;
return Token.FLOATLITERAL; // expects a call to readFloat
}
if (
maxTokenLength > 2 && this.pos + 1 < this.end &&
text.charCodeAt(this.pos) == CharCode.DOT &&
chr == CharCode.DOT &&
text.charCodeAt(this.pos + 1) == CharCode.DOT
) {
this.pos += 2;
@ -692,7 +698,8 @@ export class Tokenizer extends DiagnosticEmitter {
let commentStartPos = this.pos;
++this.pos;
if (maxTokenLength > 1 && this.pos < this.end) {
if (text.charCodeAt(this.pos) == CharCode.SLASH) { // single-line
let chr = text.charCodeAt(this.pos);
if (chr == CharCode.SLASH) { // single-line
let commentKind = CommentKind.LINE;
if (
this.pos + 1 < this.end &&
@ -716,7 +723,7 @@ export class Tokenizer extends DiagnosticEmitter {
}
break;
}
if (text.charCodeAt(this.pos) == CharCode.ASTERISK) { // multi-line
if (chr == CharCode.ASTERISK) { // multi-line
let closed = false;
while (++this.pos < this.end) {
c = text.charCodeAt(this.pos);
@ -744,7 +751,7 @@ export class Tokenizer extends DiagnosticEmitter {
}
break;
}
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
if (chr == CharCode.EQUALS) {
++this.pos;
return Token.SLASH_EQUALS;
}
@ -776,7 +783,8 @@ export class Tokenizer extends DiagnosticEmitter {
case CharCode.LESSTHAN: {
++this.pos;
if (maxTokenLength > 1 && this.pos < this.end) {
if (text.charCodeAt(this.pos) == CharCode.LESSTHAN) {
let chr = text.charCodeAt(this.pos);
if (chr == CharCode.LESSTHAN) {
++this.pos;
if (
maxTokenLength > 2 &&
@ -788,7 +796,7 @@ export class Tokenizer extends DiagnosticEmitter {
}
return Token.LESSTHAN_LESSTHAN;
}
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
if (chr == CharCode.EQUALS) {
++this.pos;
return Token.LESSTHAN_EQUALS;
}
@ -798,7 +806,8 @@ export class Tokenizer extends DiagnosticEmitter {
case CharCode.EQUALS: {
++this.pos;
if (maxTokenLength > 1 && this.pos < this.end) {
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
let chr = text.charCodeAt(this.pos);
if (chr == CharCode.EQUALS) {
++this.pos;
if (
maxTokenLength > 2 &&
@ -810,7 +819,7 @@ export class Tokenizer extends DiagnosticEmitter {
}
return Token.EQUALS_EQUALS;
}
if (text.charCodeAt(this.pos) == CharCode.GREATERTHAN) {
if (chr == CharCode.GREATERTHAN) {
++this.pos;
return Token.EQUALS_GREATERTHAN;
}
@ -820,10 +829,12 @@ export class Tokenizer extends DiagnosticEmitter {
case CharCode.GREATERTHAN: {
++this.pos;
if (maxTokenLength > 1 && this.pos < this.end) {
if (text.charCodeAt(this.pos) == CharCode.GREATERTHAN) {
let chr = text.charCodeAt(this.pos);
if (chr == CharCode.GREATERTHAN) {
++this.pos;
if (maxTokenLength > 2 && this.pos < this.end) {
if (text.charCodeAt(this.pos) == CharCode.GREATERTHAN) {
chr = text.charCodeAt(this.pos);
if (chr == CharCode.GREATERTHAN) {
++this.pos;
if (
maxTokenLength > 3 && this.pos < this.end &&
@ -834,14 +845,14 @@ export class Tokenizer extends DiagnosticEmitter {
}
return Token.GREATERTHAN_GREATERTHAN_GREATERTHAN;
}
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
if (chr == CharCode.EQUALS) {
++this.pos;
return Token.GREATERTHAN_GREATERTHAN_EQUALS;
}
}
return Token.GREATERTHAN_GREATERTHAN;
}
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
if (chr == CharCode.EQUALS) {
++this.pos;
return Token.GREATERTHAN_EQUALS;
}
@ -878,11 +889,12 @@ export class Tokenizer extends DiagnosticEmitter {
case CharCode.BAR: {
++this.pos;
if (maxTokenLength > 1 && this.pos < this.end) {
if (text.charCodeAt(this.pos) == CharCode.BAR) {
let chr = text.charCodeAt(this.pos);
if (chr == CharCode.BAR) {
++this.pos;
return Token.BAR_BAR;
}
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
if (chr == CharCode.EQUALS) {
++this.pos;
return Token.BAR_EQUALS;
}
@ -917,7 +929,7 @@ export class Tokenizer extends DiagnosticEmitter {
let keywordText = text.substring(posBefore, this.pos);
let keywordToken = tokenFromKeyword(keywordText);
if (
keywordToken != Token.INVALID &&
keywordToken !== Token.INVALID &&
identifierHandling !== IdentifierHandling.ALWAYS &&
!(
identifierHandling === IdentifierHandling.PREFER &&
@ -1148,7 +1160,7 @@ export class Tokenizer extends DiagnosticEmitter {
continue;
}
let c = text.charCodeAt(this.pos);
if (c == CharCode.SLASH && !escaped) break;
if (!escaped && c == CharCode.SLASH) break;
if (isLineBreak(c)) {
this.error(
DiagnosticCode.Unterminated_regular_expression_literal,
@ -1202,20 +1214,20 @@ export class Tokenizer extends DiagnosticEmitter {
testInteger(): bool {
var text = this.source.text;
if (text.charCodeAt(this.pos) == CharCode._0 && this.pos + 1 < this.end) {
if (this.pos + 1 < this.end && text.charCodeAt(this.pos) == CharCode._0) {
switch (text.charCodeAt(this.pos + 2)) {
case CharCode.X:
case CharCode.x:
case CharCode.B:
case CharCode.X:
case CharCode.b:
case CharCode.O:
case CharCode.o: return true;
case CharCode.B:
case CharCode.o:
case CharCode.O: return true;
}
}
var pos = this.pos;
while (pos < this.end) {
let c = text.charCodeAt(pos);
if (c == CharCode.DOT || c == CharCode.E || c == CharCode.e) {
if (c == CharCode.DOT || c == CharCode.e || c == CharCode.E) {
return false;
}
if ((c < CharCode._0 || c > CharCode._9) && c != CharCode._) break;
@ -1227,20 +1239,20 @@ export class Tokenizer extends DiagnosticEmitter {
readInteger(): I64 {
var text = this.source.text;
if (text.charCodeAt(this.pos) == CharCode._0 && this.pos + 2 < this.end) {
if (this.pos + 2 < this.end && text.charCodeAt(this.pos) == CharCode._0) {
switch (text.charCodeAt(this.pos + 1)) {
case CharCode.X:
case CharCode.x: {
case CharCode.x:
case CharCode.X: {
this.pos += 2;
return this.readHexInteger();
}
case CharCode.B:
case CharCode.b: {
case CharCode.b:
case CharCode.B: {
this.pos += 2;
return this.readBinaryInteger();
}
case CharCode.O:
case CharCode.o: {
case CharCode.o:
case CharCode.O: {
this.pos += 2;
return this.readOctalInteger();
}
@ -1262,29 +1274,29 @@ export class Tokenizer extends DiagnosticEmitter {
readHexInteger(): I64 {
var text = this.source.text;
var start = this.pos;
var value = i64_new(0, 0);
var i64_16 = i64_new(16, 0);
var value = i64_new(0);
var i64_4 = i64_new(4);
var sepEnd = start;
while (this.pos < this.end) {
let pos = this.pos;
let c = text.charCodeAt(pos);
if (c >= CharCode._0 && c <= CharCode._9) {
// value = value * 16 + c - CharCode._0;
// value = (value << 4) + c - CharCode._0;
value = i64_add(
i64_mul(value, i64_16),
i64_new(c - CharCode._0, 0)
i64_shl(value, i64_4),
i64_new(c - CharCode._0)
);
} else if (c >= CharCode.A && c <= CharCode.F) {
// value = value * 16 + 10 + c - CharCode.A;
// value = (value << 4) + 10 + c - CharCode.A;
value = i64_add(
i64_mul(value, i64_16),
i64_new(10 + c - CharCode.A, 0)
i64_shl(value, i64_4),
i64_new(10 + c - CharCode.A)
);
} else if (c >= CharCode.a && c <= CharCode.f) {
// value = value * 16 + 10 + c - CharCode.a;
// value = (value << 4) + 10 + c - CharCode.a;
value = i64_add(
i64_mul(value, i64_16),
i64_new(10 + c - CharCode.a, 0)
i64_shl(value, i64_4),
i64_new(10 + c - CharCode.a)
);
} else if (c == CharCode._) {
if (sepEnd == pos) {
@ -1318,8 +1330,8 @@ export class Tokenizer extends DiagnosticEmitter {
readDecimalInteger(): I64 {
var text = this.source.text;
var start = this.pos;
var value = i64_new(0, 0);
var i64_10 = i64_new(10, 0);
var value = i64_new(0);
var i64_10 = i64_new(10);
var sepEnd = start;
while (this.pos < this.end) {
let pos = this.pos;
@ -1328,7 +1340,7 @@ export class Tokenizer extends DiagnosticEmitter {
// value = value * 10 + c - CharCode._0;
value = i64_add(
i64_mul(value, i64_10),
i64_new(c - CharCode._0, 0)
i64_new(c - CharCode._0)
);
} else if (c == CharCode._) {
if (sepEnd == pos) {
@ -1362,17 +1374,17 @@ export class Tokenizer extends DiagnosticEmitter {
readOctalInteger(): I64 {
var text = this.source.text;
var start = this.pos;
var value = i64_new(0, 0);
var i64_8 = i64_new(8, 0);
var value = i64_new(0);
var i64_3 = i64_new(3);
var sepEnd = start;
while (this.pos < this.end) {
let pos = this.pos;
let c = text.charCodeAt(pos);
if (c >= CharCode._0 && c <= CharCode._7) {
// value = value * 8 + c - CharCode._0;
// value = (value << 3) + c - CharCode._0;
value = i64_add(
i64_mul(value, i64_8),
i64_new(c - CharCode._0, 0)
i64_shl(value, i64_3),
i64_new(c - CharCode._0)
);
} else if (c == CharCode._) {
if (sepEnd == pos) {
@ -1406,23 +1418,19 @@ export class Tokenizer extends DiagnosticEmitter {
readBinaryInteger(): I64 {
var text = this.source.text;
var start = this.pos;
var value = i64_new(0, 0);
var i64_2 = i64_new(2, 0);
var i64_1 = i64_new(1, 0);
var value = i64_new(0);
var i64_1 = i64_new(1);
var sepEnd = start;
while (this.pos < this.end) {
let pos = this.pos;
let c = text.charCodeAt(pos);
if (c == CharCode._0) {
// value = value * 2;
value = i64_mul(
value,
i64_2
);
// value = (value << 1);
value = i64_shl(value, i64_1);
} else if (c == CharCode._1) {
// value = value * 2 + 1;
// value = (value << 1) + 1;
value = i64_add(
i64_mul(value, i64_2),
i64_shl(value, i64_1),
i64_1
);
} else if (c == CharCode._) {
@ -1483,12 +1491,10 @@ export class Tokenizer extends DiagnosticEmitter {
}
if (this.pos < this.end) {
let c = text.charCodeAt(this.pos);
if (c == CharCode.E || c == CharCode.e) {
if (c == CharCode.e || c == CharCode.E) {
if (
++this.pos < this.end && (
text.charCodeAt(this.pos) == CharCode.MINUS ||
text.charCodeAt(this.pos) == CharCode.PLUS
) &&
++this.pos < this.end &&
(c = text.charCodeAt(this.pos)) == CharCode.MINUS || c == CharCode.PLUS &&
isDecimalDigit(text.charCodeAt(this.pos + 1))
) {
++this.pos;
@ -1512,11 +1518,11 @@ export class Tokenizer extends DiagnosticEmitter {
while (this.pos < this.end) {
let c = text.charCodeAt(this.pos++);
if (c >= CharCode._0 && c <= CharCode._9) {
value = value * 16 + c - CharCode._0;
value = (value << 4) + c - CharCode._0;
} else if (c >= CharCode.A && c <= CharCode.F) {
value = value * 16 + 10 + c - CharCode.A;
value = (value << 4) + c + (10 - CharCode.A);
} else if (c >= CharCode.a && c <= CharCode.f) {
value = value * 16 + 10 + c - CharCode.a;
value = (value << 4) + c + (10 - CharCode.a);
} else {
this.error(
DiagnosticCode.Hexadecimal_digit_expected,
@ -1572,8 +1578,8 @@ export class Tokenizer extends DiagnosticEmitter {
return value32 < 65536
? String.fromCharCode(value32)
: String.fromCharCode(
(((value32 - 65536) / 1024 | 0) + 0xD800) as i32,
( (value32 - 65536) % 1024 + 0xDC00) as i32
((value32 - 65536) >>> 10) + 0xD800,
((value32 - 65536) & 1023) + 0xDC00
);
}

View File

@ -184,10 +184,10 @@ export function isOctalDigit(c: i32): bool {
/** Tests if the specified character code is a valid start of an identifier. */
export function isIdentifierStart(c: i32): bool {
return c >= CharCode.A && c <= CharCode.Z
|| c >= CharCode.a && c <= CharCode.z
|| c == CharCode.DOLLAR
return c >= CharCode.a && c <= CharCode.z
|| c >= CharCode.A && c <= CharCode.Z
|| c == CharCode._
|| c == CharCode.DOLLAR
|| c > 0x7f && isUnicodeIdentifierStart(c);
}
@ -198,11 +198,11 @@ export function isKeywordCharacter(c: i32): bool {
/** Tests if the specified character code is a valid part of an identifier. */
export function isIdentifierPart(c: i32): bool {
return c >= CharCode.A && c <= CharCode.Z
|| c >= CharCode.a && c <= CharCode.z
return c >= CharCode.a && c <= CharCode.z
|| c >= CharCode.A && c <= CharCode.Z
|| c >= CharCode._0 && c <= CharCode._9
|| c == CharCode.DOLLAR
|| c == CharCode._
|| c == CharCode.DOLLAR
|| c > 0x7f && isUnicodeIdentifierPart(c);
}
@ -349,14 +349,16 @@ function lookupInUnicodeMap(code: u16, map: u16[]): bool {
var lo = 0;
var hi = map.length;
var mid: i32;
var midVal: u16;
while (lo + 1 < hi) {
mid = lo + (hi - lo) / 2;
mid -= mid % 2;
if (map[mid] <= code && code <= map[mid + 1]) {
mid = lo + ((hi - lo) >> 1);
mid -= (mid & 1);
midVal = map[mid];
if (midVal <= code && code <= map[mid + 1]) {
return true;
}
if (code < map[mid]) {
if (code < midVal) {
hi = mid;
} else {
lo = mid + 2;

View File

@ -4,6 +4,10 @@ import {
CharCode
} from "./charcode";
import {
PATH_DELIMITER
} from "../common";
const separator = CharCode.SLASH;
/**
@ -99,13 +103,19 @@ export function resolvePath(normalizedPath: string, origin: string): string {
return normalizedPath;
}
return normalizePath(
dirname(origin) + String.fromCharCode(separator) + normalizedPath
dirname(origin) + PATH_DELIMITER + normalizedPath
);
}
/** Obtains the directory portion of a normalized path. */
export function dirname(normalizedPath: string): string {
var pos = normalizedPath.length;
if (pos <= 1) {
if (pos == 0) return ".";
if (normalizedPath.charCodeAt(0) == separator) {
return normalizedPath;
}
}
while (--pos > 0) {
if (normalizedPath.charCodeAt(pos) == separator) {
return normalizedPath.substring(0, pos);