blob: e55aa543954efdb2157a5b22861fa2cfc0b2d230 [file] [log] [blame]
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of dart2js.ir_pickler;
class Unpickler {
final Compiler compiler;
final IrConstantPool constantPool;
Unpickler(this.compiler, this.constantPool);
List<int> data;
int offset;
/** For each entry index, the corresponding unpickled object. */
List<Object> unpickled;
/** Counter for entries in [unpickled]. */
int index;
/**
* This buffer is used in [readConstant] to reconstruct a double value from
* a sequence of bytes.
*/
ByteData doubleData = new ByteData(8);
ConstantSystem get constantSystem => compiler.backend.constantSystem;
ir.Function unpickle(List<int> data) {
this.data = data;
offset = 0;
int numEntries = readInt();
unpickled = new List<Object>(numEntries);
index = 0;
return readNode();
}
int readByte() {
return data[offset++];
}
int readInt() {
int result = 0;
int next;
for (int i = 0; true; i += 7) {
next = readByte();
result |= (next >> 1) << i;
if ((next & 1) == 0) break;
}
bool isNegative = (result & 1) == 1;
result >>= 1;
return isNegative ? -result : result;
}
String readString() {
int tag = readByte();
int length = readInt();
List<int> bytes = new Uint8List(length);
for (int i = 0; i < length; i++) {
bytes[i] = readByte();
}
if (tag == Pickles.STRING_ASCII) {
return new String.fromCharCodes(bytes);
} else if (tag == Pickles.STRING_UTF8) {
return UTF8.decode(bytes);
} else {
compiler.internalError("Unexpected string tag: $tag");
return null;
}
}
Element readElement() {
int elementIndex = readInt();
return constantPool.get(elementIndex);
}
Selector readSelector() {
int tag = readByte();
if (tag == Pickles.BACKREFERENCE) {
return readBackReference();
}
assert(tag == Pickles.SELECTOR_UNTYPED);
int entryIndex = index++;
SelectorKind kind = Pickles.selectorKindFromId[readInt()];
String name = readString();
Element library = readElement();
int argumentsCount = readInt();
int namedArgumentsCount = readInt();
List<String> namedArguments = new List<String>(namedArgumentsCount);
for (int i = 0; i < namedArgumentsCount; i++) {
namedArguments[i] = readString();
}
Selector result = new Selector(
kind, name, library, argumentsCount, namedArguments);
unpickled[entryIndex] = result;
return result;
}
/**
* Reads a [ir.Node]. Expression nodes are added to the [unpickled] map to
* enable unpickling back references.
*/
ir.Node readNode() {
int tag = readByte();
if (Pickles.isExpressionTag(tag)) {
return readExpressionNode(tag);
} else if (tag == Pickles.NODE_RETURN) {
return readReturnNode();
} else {
compiler.internalError("Unexpected entry tag: $tag");
return null;
}
}
ir.Expression readExpressionNode(int tag) {
int entryIndex = index++;
ir.Expression result;
if (tag == Pickles.NODE_CONST) {
result = readConstantNode();
} else if (tag == Pickles.NODE_FUNCTION) {
result = readFunctionNode();
} else if (tag == Pickles.NODE_INVOKE_STATIC) {
result = readInvokeStaticNode();
} else {
compiler.internalError("Unexpected expression entry tag: $tag");
}
return unpickled[entryIndex] = result;
}
Object readBackReference() {
int indexDelta = readInt();
int entryIndex = index - indexDelta;
assert(unpickled[entryIndex] != null);
return unpickled[entryIndex];
}
List<ir.Expression> readExpressionBackReferenceList() {
int length = readInt();
List<ir.Expression> result = new List<ir.Expression>(length);
for (int i = 0; i < length; i++) {
result[i] = readBackReference();
}
return result;
}
List<ir.Node> readNodeList() {
int length = readInt();
List<ir.Node> nodes = new List<ir.Node>(length);
for (int i = 0; i < length; i++) {
nodes[i] = readNode();
}
return nodes;
}
ir.Function readFunctionNode() {
var position = readPosition();
int endOffset = readInt();
int namePosition = readInt();
List<ir.Node> statements = readNodeList();
return new ir.Function(position, endOffset, namePosition, statements);
}
ir.Constant readConstantNode() {
var position = readPosition();
Constant constant = readConstant();
return new ir.Constant(position, constant);
}
ir.Return readReturnNode() {
var position = readPosition();
ir.Expression value = readBackReference();
return new ir.Return(position, value);
}
ir.InvokeStatic readInvokeStaticNode() {
var position = readPosition();
FunctionElement functionElement = readElement();
Selector selector = readSelector();
List<ir.Expression> arguments = readExpressionBackReferenceList();
return new ir.InvokeStatic(position, functionElement, selector, arguments);
}
/* int | PositionWithIdentifierName */ readPosition() {
if (readByte() == Pickles.POSITION_OFFSET) {
return readInt();
} else {
String sourceName = readString();
int offset = readInt();
return new ir.PositionWithIdentifierName(offset, sourceName);
}
}
Constant readConstant() {
int tag = readByte();
switch(tag) {
case Pickles.CONST_BOOL:
return constantSystem.createBool(readByte() == 1);
case Pickles.CONST_INT:
return constantSystem.createInt(readInt());
case Pickles.CONST_DOUBLE:
for (int i = 0; i < 8; i++) {
doubleData.setUint8(i, readByte());
}
double value = doubleData.getFloat64(0, Endianness.BIG_ENDIAN);
return constantSystem.createDouble(value);
case Pickles.CONST_STRING_LITERAL:
case Pickles.CONST_STRING_RAW:
case Pickles.CONST_STRING_ESCAPED:
case Pickles.CONST_STRING_CONS:
return constantSystem.createString(readDartString(tag));
case Pickles.CONST_NULL:
return constantSystem.createNull();
default:
compiler.internalError("Unexpected constant tag: $tag");
return null;
}
}
ast.DartString readDartString(int tag) {
switch(tag) {
case Pickles.CONST_STRING_LITERAL:
return new ast.LiteralDartString(readString());
case Pickles.CONST_STRING_RAW:
return new ast.RawSourceDartString(readString(), readInt());
case Pickles.CONST_STRING_ESCAPED:
return new ast.EscapedSourceDartString(readString(), readInt());
case Pickles.CONST_STRING_CONS:
return new ast.ConsDartString(
readDartString(readByte()), readDartString(readByte()));
default:
compiler.internalError("Unexpected dart string tag: $tag");
return null;
}
}
}