diff --git a/js/src/jit/Bailouts.cpp b/js/src/jit/Bailouts.cpp index c00f3a893936..da993e4f8db6 100644 --- a/js/src/jit/Bailouts.cpp +++ b/js/src/jit/Bailouts.cpp @@ -12,7 +12,7 @@ #include "jit/Ion.h" #include "jit/IonSpewer.h" #include "jit/JitCompartment.h" -#include "jit/SnapshotReader.h" +#include "jit/Snapshots.h" #include "jit/IonFrameIterator-inl.h" #include "vm/Stack-inl.h" diff --git a/js/src/jit/Bailouts.h b/js/src/jit/Bailouts.h index 2d17ff397fe4..50e2e817d54a 100644 --- a/js/src/jit/Bailouts.h +++ b/js/src/jit/Bailouts.h @@ -91,9 +91,6 @@ namespace jit { static const BailoutId INVALID_BAILOUT_ID = BailoutId(-1); -static const uint32_t BAILOUT_KIND_BITS = 3; -static const uint32_t BAILOUT_RESUME_BITS = 1; - // Keep this arbitrarily small for now, for testing. static const uint32_t BAILOUT_TABLE_SIZE = 16; diff --git a/js/src/jit/BaselineBailouts.cpp b/js/src/jit/BaselineBailouts.cpp index 5275b8f76bb8..7a4cc4cace1b 100644 --- a/js/src/jit/BaselineBailouts.cpp +++ b/js/src/jit/BaselineBailouts.cpp @@ -475,7 +475,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC, if (excInfo) exprStackSlots = excInfo->numExprSlots; else - exprStackSlots = iter.slots() - (script->nfixed() + CountArgSlots(script, fun)); + exprStackSlots = iter.allocations() - (script->nfixed() + CountArgSlots(script, fun)); builder.resetFramePushed(); @@ -623,9 +623,9 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC, size_t thisvOffset = builder.framePushed() + IonJSFrameLayout::offsetOfThis(); *builder.valuePointerAtStackOffset(thisvOffset) = thisv; - JS_ASSERT(iter.slots() >= CountArgSlots(script, fun)); + JS_ASSERT(iter.allocations() >= CountArgSlots(script, fun)); IonSpew(IonSpew_BaselineBailouts, " frame slots %u, nargs %u, nfixed %u", - iter.slots(), fun->nargs(), script->nfixed()); + iter.allocations(), fun->nargs(), script->nfixed()); if (!callerPC) { // This is the first frame. Store the formals in a Vector until we diff --git a/js/src/jit/IonCode.h b/js/src/jit/IonCode.h index 3fe0f4e84cd9..cdd0c8563193 100644 --- a/js/src/jit/IonCode.h +++ b/js/src/jit/IonCode.h @@ -28,14 +28,6 @@ class AsmJSModule; namespace jit { -// The maximum size of any buffer associated with an assembler or code object. -// This is chosen to not overflow a signed integer, leaving room for an extra -// bit on offsets. -static const uint32_t MAX_BUFFER_SIZE = (1 << 30) - 1; - -// Maximum number of scripted arg slots. -static const uint32_t SNAPSHOT_MAX_NARGS = 127; - class MacroAssembler; class CodeOffsetLabel; class PatchableBackedge; diff --git a/js/src/jit/IonFrameIterator.h b/js/src/jit/IonFrameIterator.h index 220725f7eb06..a34e7a2e0baf 100644 --- a/js/src/jit/IonFrameIterator.h +++ b/js/src/jit/IonFrameIterator.h @@ -13,7 +13,7 @@ #include "jstypes.h" #include "jit/IonCode.h" -#include "jit/SnapshotReader.h" +#include "jit/Snapshots.h" namespace js { class ActivationIterator; @@ -245,9 +245,9 @@ class SnapshotIterator : public SnapshotReader bool hasStack(const Location &loc); uintptr_t fromStack(const Location &loc); - Value slotValue(const Slot &slot); - bool slotReadable(const Slot &slot); - void warnUnreadableSlot(); + Value allocationValue(const RValueAllocation &a); + bool allocationReadable(const RValueAllocation &a); + void warnUnreadableAllocation(); public: SnapshotIterator(IonScript *ionScript, SnapshotOffset snapshotOffset, @@ -256,15 +256,19 @@ class SnapshotIterator : public SnapshotReader SnapshotIterator(const IonBailoutIterator &iter); SnapshotIterator(); + Value skip() { + readAllocation(); + return UndefinedValue(); + } Value read() { - return slotValue(readSlot()); + return allocationValue(readAllocation()); } Value maybeRead(bool silentFailure = false) { - Slot s = readSlot(); - if (slotReadable(s)) - return slotValue(s); + RValueAllocation a = readAllocation(); + if (allocationReadable(a)) + return allocationValue(a); if (!silentFailure) - warnUnreadableSlot(); + warnUnreadableAllocation(); return UndefinedValue(); } @@ -308,15 +312,15 @@ class SnapshotIterator : public SnapshotReader } } - Value maybeReadSlotByIndex(size_t index) { + Value maybeReadAllocByIndex(size_t index) { while (index--) { - JS_ASSERT(moreSlots()); + JS_ASSERT(moreAllocations()); skip(); } Value s = maybeRead(true); - while (moreSlots()) + while (moreAllocations()) skip(); return s; @@ -427,8 +431,8 @@ class InlineFrameIteratorMaybeGC // Skip over all slots untill we get to the last slots (= arguments slots of callee) // the +3 is for [this], [returnvalue], [scopechain], and maybe +1 for [argsObj] - JS_ASSERT(parent_s.slots() >= nactual + 3 + argsObjAdj); - unsigned skip = parent_s.slots() - nactual - 3 - argsObjAdj; + JS_ASSERT(parent_s.allocations() >= nactual + 3 + argsObjAdj); + unsigned skip = parent_s.allocations() - nactual - 3 - argsObjAdj; for (unsigned j = 0; j < skip; j++) parent_s.skip(); diff --git a/js/src/jit/IonFrames.cpp b/js/src/jit/IonFrames.cpp index 98049020fa41..0868776666d3 100644 --- a/js/src/jit/IonFrames.cpp +++ b/js/src/jit/IonFrames.cpp @@ -21,7 +21,7 @@ #include "jit/ParallelFunctions.h" #include "jit/PcScriptCache.h" #include "jit/Safepoints.h" -#include "jit/SnapshotReader.h" +#include "jit/Snapshots.h" #include "jit/VMFunctions.h" #include "vm/ForkJoin.h" #include "vm/Interpreter.h" @@ -1333,14 +1333,14 @@ SnapshotIterator::fromRegister(const Location &loc) bool SnapshotIterator::hasStack(const Location &loc) { - JS_ASSERT(loc.isStackSlot()); + JS_ASSERT(loc.isStackOffset()); return true; } uintptr_t SnapshotIterator::fromStack(const Location &loc) { - return ReadFrameSlot(fp_, loc.stackSlot()); + return ReadFrameSlot(fp_, loc.stackOffset()); } static Value @@ -1373,29 +1373,29 @@ FromTypedPayload(JSValueType type, uintptr_t payload) } bool -SnapshotIterator::slotReadable(const Slot &slot) +SnapshotIterator::allocationReadable(const RValueAllocation &alloc) { - switch (slot.mode()) { - case Slot::DOUBLE_REG: - return machine_.has(slot.floatReg()); + switch (alloc.mode()) { + case RValueAllocation::DOUBLE_REG: + return machine_.has(alloc.floatReg()); - case Slot::TYPED_REG: - return machine_.has(slot.reg()); + case RValueAllocation::TYPED_REG: + return machine_.has(alloc.reg()); #if defined(JS_NUNBOX32) - case Slot::UNTYPED_REG_REG: - return hasRegister(slot.type()) && hasRegister(slot.payload()); - case Slot::UNTYPED_REG_STACK: - return hasRegister(slot.type()) && hasStack(slot.payload()); - case Slot::UNTYPED_STACK_REG: - return hasStack(slot.type()) && hasRegister(slot.payload()); - case Slot::UNTYPED_STACK_STACK: - return hasStack(slot.type()) && hasStack(slot.payload()); + case RValueAllocation::UNTYPED_REG_REG: + return hasRegister(alloc.type()) && hasRegister(alloc.payload()); + case RValueAllocation::UNTYPED_REG_STACK: + return hasRegister(alloc.type()) && hasStack(alloc.payload()); + case RValueAllocation::UNTYPED_STACK_REG: + return hasStack(alloc.type()) && hasRegister(alloc.payload()); + case RValueAllocation::UNTYPED_STACK_STACK: + return hasStack(alloc.type()) && hasStack(alloc.payload()); #elif defined(JS_PUNBOX64) - case Slot::UNTYPED_REG: - return hasRegister(slot.value()); - case Slot::UNTYPED_STACK: - return hasStack(slot.value()); + case RValueAllocation::UNTYPED_REG: + return hasRegister(alloc.value()); + case RValueAllocation::UNTYPED_STACK: + return hasStack(alloc.value()); #endif default: @@ -1404,107 +1404,107 @@ SnapshotIterator::slotReadable(const Slot &slot) } Value -SnapshotIterator::slotValue(const Slot &slot) +SnapshotIterator::allocationValue(const RValueAllocation &alloc) { - switch (slot.mode()) { - case Slot::DOUBLE_REG: - return DoubleValue(machine_.read(slot.floatReg())); + switch (alloc.mode()) { + case RValueAllocation::DOUBLE_REG: + return DoubleValue(machine_.read(alloc.floatReg())); - case Slot::FLOAT32_REG: + case RValueAllocation::FLOAT32_REG: { union { double d; float f; } pun; - pun.d = machine_.read(slot.floatReg()); + pun.d = machine_.read(alloc.floatReg()); // The register contains the encoding of a float32. We just read // the bits without making any conversion. return Float32Value(pun.f); } - case Slot::FLOAT32_STACK: - return Float32Value(ReadFrameFloat32Slot(fp_, slot.stackSlot())); + case RValueAllocation::FLOAT32_STACK: + return Float32Value(ReadFrameFloat32Slot(fp_, alloc.stackOffset())); - case Slot::TYPED_REG: - return FromTypedPayload(slot.knownType(), machine_.read(slot.reg())); + case RValueAllocation::TYPED_REG: + return FromTypedPayload(alloc.knownType(), machine_.read(alloc.reg())); - case Slot::TYPED_STACK: + case RValueAllocation::TYPED_STACK: { - switch (slot.knownType()) { + switch (alloc.knownType()) { case JSVAL_TYPE_DOUBLE: - return DoubleValue(ReadFrameDoubleSlot(fp_, slot.stackSlot())); + return DoubleValue(ReadFrameDoubleSlot(fp_, alloc.stackOffset())); case JSVAL_TYPE_INT32: - return Int32Value(ReadFrameInt32Slot(fp_, slot.stackSlot())); + return Int32Value(ReadFrameInt32Slot(fp_, alloc.stackOffset())); case JSVAL_TYPE_BOOLEAN: - return BooleanValue(ReadFrameBooleanSlot(fp_, slot.stackSlot())); + return BooleanValue(ReadFrameBooleanSlot(fp_, alloc.stackOffset())); case JSVAL_TYPE_STRING: - return FromStringPayload(ReadFrameSlot(fp_, slot.stackSlot())); + return FromStringPayload(ReadFrameSlot(fp_, alloc.stackOffset())); case JSVAL_TYPE_OBJECT: - return FromObjectPayload(ReadFrameSlot(fp_, slot.stackSlot())); + return FromObjectPayload(ReadFrameSlot(fp_, alloc.stackOffset())); default: MOZ_ASSUME_UNREACHABLE("Unexpected type"); } } #if defined(JS_NUNBOX32) - case Slot::UNTYPED_REG_REG: + case RValueAllocation::UNTYPED_REG_REG: { jsval_layout layout; - layout.s.tag = (JSValueTag) fromRegister(slot.type()); - layout.s.payload.word = fromRegister(slot.payload()); + layout.s.tag = (JSValueTag) fromRegister(alloc.type()); + layout.s.payload.word = fromRegister(alloc.payload()); return IMPL_TO_JSVAL(layout); } - case Slot::UNTYPED_REG_STACK: + case RValueAllocation::UNTYPED_REG_STACK: { jsval_layout layout; - layout.s.tag = (JSValueTag) fromRegister(slot.type()); - layout.s.payload.word = fromStack(slot.payload()); + layout.s.tag = (JSValueTag) fromRegister(alloc.type()); + layout.s.payload.word = fromStack(alloc.payload()); return IMPL_TO_JSVAL(layout); } - case Slot::UNTYPED_STACK_REG: + case RValueAllocation::UNTYPED_STACK_REG: { jsval_layout layout; - layout.s.tag = (JSValueTag) fromStack(slot.type()); - layout.s.payload.word = fromRegister(slot.payload()); + layout.s.tag = (JSValueTag) fromStack(alloc.type()); + layout.s.payload.word = fromRegister(alloc.payload()); return IMPL_TO_JSVAL(layout); } - case Slot::UNTYPED_STACK_STACK: + case RValueAllocation::UNTYPED_STACK_STACK: { jsval_layout layout; - layout.s.tag = (JSValueTag) fromStack(slot.type()); - layout.s.payload.word = fromStack(slot.payload()); + layout.s.tag = (JSValueTag) fromStack(alloc.type()); + layout.s.payload.word = fromStack(alloc.payload()); return IMPL_TO_JSVAL(layout); } #elif defined(JS_PUNBOX64) - case Slot::UNTYPED_REG: + case RValueAllocation::UNTYPED_REG: { jsval_layout layout; - layout.asBits = fromRegister(slot.value()); + layout.asBits = fromRegister(alloc.value()); return IMPL_TO_JSVAL(layout); } - case Slot::UNTYPED_STACK: + case RValueAllocation::UNTYPED_STACK: { jsval_layout layout; - layout.asBits = fromStack(slot.value()); + layout.asBits = fromStack(alloc.value()); return IMPL_TO_JSVAL(layout); } #endif - case Slot::JS_UNDEFINED: + case RValueAllocation::JS_UNDEFINED: return UndefinedValue(); - case Slot::JS_NULL: + case RValueAllocation::JS_NULL: return NullValue(); - case Slot::JS_INT32: - return Int32Value(slot.int32Value()); + case RValueAllocation::JS_INT32: + return Int32Value(alloc.int32Value()); - case Slot::CONSTANT: - return ionScript_->getConstant(slot.constantIndex()); + case RValueAllocation::CONSTANT: + return ionScript_->getConstant(alloc.constantIndex()); default: MOZ_ASSUME_UNREACHABLE("huh?"); @@ -1595,14 +1595,14 @@ InlineFrameIteratorMaybeGC::findNextFrame() JS_ASSERT(numActualArgs_ != 0xbadbad); // Skip over non-argument slots, as well as |this|. - unsigned skipCount = (si_.slots() - 1) - numActualArgs_ - 1; + unsigned skipCount = (si_.allocations() - 1) - numActualArgs_ - 1; for (unsigned j = 0; j < skipCount; j++) si_.skip(); Value funval = si_.read(); - // Skip extra slots. - while (si_.moreSlots()) + // Skip extra value allocations. + while (si_.moreAllocations()) si_.skip(); si_.nextFrame(); @@ -1721,9 +1721,9 @@ IonFrameIterator::numActualArgs() const } void -SnapshotIterator::warnUnreadableSlot() +SnapshotIterator::warnUnreadableAllocation() { - fprintf(stderr, "Warning! Tried to access unreadable IonMonkey slot (possible f.arguments).\n"); + fprintf(stderr, "Warning! Tried to access unreadable value allocation (possible f.arguments).\n"); } struct DumpOp { @@ -1817,8 +1817,8 @@ InlineFrameIteratorMaybeGC::dump() const } SnapshotIterator si = snapshotIterator(); - fprintf(stderr, " slots: %u\n", si.slots() - 1); - for (unsigned i = 0; i < si.slots() - 1; i++) { + fprintf(stderr, " slots: %u\n", si.allocations() - 1); + for (unsigned i = 0; i < si.allocations() - 1; i++) { if (isFunction) { if (i == 0) fprintf(stderr, " scope chain: "); diff --git a/js/src/jit/IonTypes.h b/js/src/jit/IonTypes.h index 2e90edd647d7..c325e9bede80 100644 --- a/js/src/jit/IonTypes.h +++ b/js/src/jit/IonTypes.h @@ -17,6 +17,14 @@ namespace jit { typedef uint32_t SnapshotOffset; typedef uint32_t BailoutId; +// The maximum size of any buffer associated with an assembler or code object. +// This is chosen to not overflow a signed integer, leaving room for an extra +// bit on offsets. +static const uint32_t MAX_BUFFER_SIZE = (1 << 30) - 1; + +// Maximum number of scripted arg slots. +static const uint32_t SNAPSHOT_MAX_NARGS = 127; + static const SnapshotOffset INVALID_SNAPSHOT_OFFSET = uint32_t(-1); // Different kinds of bailouts. When extending this enum, make sure to check @@ -41,6 +49,9 @@ enum BailoutKind Bailout_BaselineInfo }; +static const uint32_t BAILOUT_KIND_BITS = 3; +static const uint32_t BAILOUT_RESUME_BITS = 1; + #ifdef DEBUG inline const char * BailoutKindString(BailoutKind kind) diff --git a/js/src/jit/Slot.cpp b/js/src/jit/Slot.cpp deleted file mode 100644 index 739d01ac91bd..000000000000 --- a/js/src/jit/Slot.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - -#include "jit/Slot.h" - -#include "jit/CompactBuffer.h" - -using namespace js; -using namespace js::jit; - -// [slot] Information on how to reify a js::Value from an Ion frame. The -// first byte is split as thus: -// Bits 0-2: JSValueType -// Bits 3-7: 5-bit register code ("reg"). -// -// JSVAL_TYPE_DOUBLE: -// If "reg" is InvalidFloatReg, this byte is followed by a -// [vws] stack offset. Otherwise, "reg" encodes an XMM register. -// -// JSVAL_TYPE_INT32: -// JSVAL_TYPE_OBJECT: -// JSVAL_TYPE_BOOLEAN: -// JSVAL_TYPE_STRING: -// If "reg" is InvalidReg1, this byte is followed by a [vws] -// stack offset. Otherwise, "reg" encodes a GPR register. -// -// JSVAL_TYPE_NULL: -// Reg value: -// 0-27: Constant integer; Int32Value(n) -// 28: Variable float32; Float register code -// 29: Variable float32; Stack index -// 30: NullValue() -// 31: Constant integer; Int32Value([vws]) -// -// JSVAL_TYPE_UNDEFINED: -// Reg value: -// 0-27: Constant value, index n into ionScript->constants() -// 28-29: unused -// 30: UndefinedValue() -// 31: Constant value, index [vwu] into -// ionScript->constants() -// -// JSVAL_TYPE_MAGIC: (reg value is 30) -// The value is a lazy argument object. Followed by extra fields -// indicating the location of the payload. -// [vwu] reg2 (0-29) -// [vwu] reg2 (31) [vws] stack index -// -// JSVAL_TYPE_MAGIC: -// The type is not statically known. The meaning of this depends -// on the boxing style. -// -// NUNBOX32: -// Followed by a type and payload indicator that are one of -// the following: -// code=0 [vws] stack slot, [vws] stack slot -// code=1 [vws] stack slot, reg -// code=2 reg, [vws] stack slot -// code=3 reg, reg -// -// PUNBOX64: -// "reg" is InvalidReg1: byte is followed by a [vws] stack -// offset containing a Value. -// -// Otherwise, "reg" is a register containing a Value. -// - -#ifdef JS_NUNBOX32 -static const uint32_t NUNBOX32_STACK_STACK = 0; -static const uint32_t NUNBOX32_STACK_REG = 1; -static const uint32_t NUNBOX32_REG_STACK = 2; -static const uint32_t NUNBOX32_REG_REG = 3; -#endif - -static const uint32_t MAX_TYPE_FIELD_VALUE = 7; - -static const uint32_t MAX_REG_FIELD_VALUE = 31; -static const uint32_t ESC_REG_FIELD_INDEX = 31; -static const uint32_t ESC_REG_FIELD_CONST = 30; -static const uint32_t ESC_REG_FIELD_FLOAT32_STACK = 29; -static const uint32_t ESC_REG_FIELD_FLOAT32_REG = 28; -static const uint32_t MIN_REG_FIELD_ESC = 28; - -Slot -Slot::read(CompactBufferReader &reader) -{ - uint8_t b = reader.readByte(); - - JSValueType type = JSValueType(b & 0x7); - uint32_t code = b >> 3; - - switch (type) { - case JSVAL_TYPE_DOUBLE: - if (code < MIN_REG_FIELD_ESC) - return DoubleSlot(FloatRegister::FromCode(code)); - JS_ASSERT(code == ESC_REG_FIELD_INDEX); - return TypedSlot(type, reader.readSigned()); - - case JSVAL_TYPE_INT32: - case JSVAL_TYPE_STRING: - case JSVAL_TYPE_OBJECT: - case JSVAL_TYPE_BOOLEAN: - if (code < MIN_REG_FIELD_ESC) - return TypedSlot(type, Register::FromCode(code)); - JS_ASSERT(code == ESC_REG_FIELD_INDEX); - return TypedSlot(type, reader.readSigned()); - - case JSVAL_TYPE_NULL: - if (code == ESC_REG_FIELD_CONST) - return NullSlot(); - if (code == ESC_REG_FIELD_INDEX) - return Int32Slot(reader.readSigned()); - if (code == ESC_REG_FIELD_FLOAT32_REG) - return Float32Slot(FloatRegister::FromCode(reader.readUnsigned())); - if (code == ESC_REG_FIELD_FLOAT32_STACK) - return Float32Slot(reader.readSigned()); - return Int32Slot(code); - - case JSVAL_TYPE_UNDEFINED: - if (code == ESC_REG_FIELD_CONST) - return UndefinedSlot(); - if (code == ESC_REG_FIELD_INDEX) - return ConstantPoolSlot(reader.readUnsigned()); - return ConstantPoolSlot(code); - - case JSVAL_TYPE_MAGIC: - { - if (code == ESC_REG_FIELD_CONST) { - uint8_t reg2 = reader.readUnsigned(); - if (reg2 != ESC_REG_FIELD_INDEX) - return TypedSlot(type, Register::FromCode(reg2)); - return TypedSlot(type, reader.readSigned()); - } - -#ifdef JS_NUNBOX32 - int32_t type, payload; - switch (code) { - case NUNBOX32_STACK_STACK: - type = reader.readSigned(); - payload = reader.readSigned(); - return UntypedSlot(type, payload); - case NUNBOX32_STACK_REG: - type = reader.readSigned(); - payload = reader.readByte(); - return UntypedSlot(type, Register::FromCode(payload)); - case NUNBOX32_REG_STACK: - type = reader.readByte(); - payload = reader.readSigned(); - return UntypedSlot(Register::FromCode(type), payload); - case NUNBOX32_REG_REG: - type = reader.readByte(); - payload = reader.readByte(); - return UntypedSlot(Register::FromCode(type), - Register::FromCode(payload)); - default: - MOZ_ASSUME_UNREACHABLE("bad code"); - break; - } -#elif JS_PUNBOX64 - if (code < MIN_REG_FIELD_ESC) - return UntypedSlot(Register::FromCode(code)); - JS_ASSERT(code == ESC_REG_FIELD_INDEX); - return UntypedSlot(reader.readSigned()); -#endif - } - - default: - MOZ_ASSUME_UNREACHABLE("bad type"); - break; - } - - MOZ_ASSUME_UNREACHABLE("huh?"); -} - -void -Slot::writeSlotHeader(CompactBufferWriter &writer, JSValueType type, uint32_t regCode) const -{ - JS_ASSERT(uint32_t(type) <= MAX_TYPE_FIELD_VALUE); - JS_ASSERT(uint32_t(regCode) <= MAX_REG_FIELD_VALUE); - JS_STATIC_ASSERT(Registers::Total < MIN_REG_FIELD_ESC); - - uint8_t byte = uint32_t(type) | (regCode << 3); - writer.writeByte(byte); -} - -void -Slot::write(CompactBufferWriter &writer) const -{ - switch (mode()) { - case CONSTANT: { - if (constantIndex() < MIN_REG_FIELD_ESC) { - writeSlotHeader(writer, JSVAL_TYPE_UNDEFINED, constantIndex()); - } else { - writeSlotHeader(writer, JSVAL_TYPE_UNDEFINED, ESC_REG_FIELD_INDEX); - writer.writeUnsigned(constantIndex()); - } - break; - } - - case DOUBLE_REG: { - writeSlotHeader(writer, JSVAL_TYPE_DOUBLE, floatReg().code()); - break; - } - - case FLOAT32_REG: { - writeSlotHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_FLOAT32_REG); - writer.writeUnsigned(floatReg().code()); - break; - } - - case FLOAT32_STACK: { - writeSlotHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_FLOAT32_STACK); - writer.writeSigned(stackSlot()); - break; - } - - case TYPED_REG: { - writeSlotHeader(writer, knownType(), reg().code()); - break; - } - case TYPED_STACK: { - writeSlotHeader(writer, knownType(), ESC_REG_FIELD_INDEX); - writer.writeSigned(stackSlot()); - break; - } -#if defined(JS_NUNBOX32) - case UNTYPED_REG_REG: { - writeSlotHeader(writer, JSVAL_TYPE_MAGIC, NUNBOX32_REG_REG); - writer.writeByte(type().reg().code()); - writer.writeByte(payload().reg().code()); - break; - } - case UNTYPED_REG_STACK: { - writeSlotHeader(writer, JSVAL_TYPE_MAGIC, NUNBOX32_REG_STACK); - writer.writeByte(type().reg().code()); - writer.writeSigned(payload().stackSlot()); - break; - } - case UNTYPED_STACK_REG: { - writeSlotHeader(writer, JSVAL_TYPE_MAGIC, NUNBOX32_STACK_REG); - writer.writeSigned(type().stackSlot()); - writer.writeByte(payload().reg().code()); - break; - } - case UNTYPED_STACK_STACK: { - writeSlotHeader(writer, JSVAL_TYPE_MAGIC, NUNBOX32_STACK_STACK); - writer.writeSigned(type().stackSlot()); - writer.writeSigned(payload().stackSlot()); - break; - } -#elif defined(JS_PUNBOX64) - case UNTYPED_REG: { - writeSlotHeader(writer, JSVAL_TYPE_MAGIC, value().reg().code()); - break; - } - case UNTYPED_STACK: { - writeSlotHeader(writer, JSVAL_TYPE_MAGIC, ESC_REG_FIELD_INDEX); - writer.writeSigned(value().stackSlot()); - break; - } -#endif - case JS_UNDEFINED: { - writeSlotHeader(writer, JSVAL_TYPE_UNDEFINED, ESC_REG_FIELD_CONST); - break; - } - case JS_NULL: { - writeSlotHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_CONST); - break; - } - case JS_INT32: { - if (int32Value() >= 0 && uint32_t(int32Value()) < MIN_REG_FIELD_ESC) { - writeSlotHeader(writer, JSVAL_TYPE_NULL, int32Value()); - } else { - writeSlotHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_INDEX); - writer.writeSigned(int32Value()); - } - break; - } - case INVALID: { - MOZ_ASSUME_UNREACHABLE("not initialized"); - break; - } - } -} - -void -Location::dump(FILE *fp) const -{ - if (isStackSlot()) - fprintf(fp, "stack %d", stackSlot()); - else - fprintf(fp, "reg %s", reg().name()); -} - -static const char * -ValTypeToString(JSValueType type) -{ - switch (type) { - case JSVAL_TYPE_INT32: - return "int32_t"; - case JSVAL_TYPE_DOUBLE: - return "double"; - case JSVAL_TYPE_STRING: - return "string"; - case JSVAL_TYPE_BOOLEAN: - return "boolean"; - case JSVAL_TYPE_OBJECT: - return "object"; - case JSVAL_TYPE_MAGIC: - return "magic"; - default: - MOZ_ASSUME_UNREACHABLE("no payload"); - } -} - -void -Slot::dump(FILE *fp) const -{ - switch (mode()) { - case CONSTANT: - fprintf(fp, "constant (pool index %u)", constantIndex()); - break; - - case DOUBLE_REG: - fprintf(fp, "double (reg %s)", floatReg().name()); - break; - - case FLOAT32_REG: - fprintf(fp, "float32 (reg %s)", floatReg().name()); - break; - - case FLOAT32_STACK: - fprintf(fp, "float32 ("); - known_type_.payload.dump(fp); - fprintf(fp, ")"); - break; - - case TYPED_REG: - case TYPED_STACK: - fprintf(fp, "%s (", ValTypeToString(knownType())); - known_type_.payload.dump(fp); - fprintf(fp, ")"); - break; - -#if defined(JS_NUNBOX32) - case UNTYPED_REG_REG: - case UNTYPED_REG_STACK: - case UNTYPED_STACK_REG: - case UNTYPED_STACK_STACK: - fprintf(fp, "value (type = "); - type().dump(fp); - fprintf(fp, ", payload = "); - payload().dump(fp); - fprintf(fp, ")"); - break; -#elif defined(JS_PUNBOX64) - case UNTYPED_REG: - case UNTYPED_STACK: - fprintf(fp, "value ("); - value().dump(fp); - fprintf(fp, ")"); - break; -#endif - - case JS_UNDEFINED: - fprintf(fp, "undefined"); - break; - - case JS_NULL: - fprintf(fp, "null"); - break; - - case JS_INT32: - fprintf(fp, "int32_t %d", int32Value()); - break; - - case INVALID: - fprintf(fp, "invalid"); - break; - } -} diff --git a/js/src/jit/SnapshotReader.h b/js/src/jit/SnapshotReader.h deleted file mode 100644 index 8d53e3e692db..000000000000 --- a/js/src/jit/SnapshotReader.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef jit_SnapshotReader_h -#define jit_SnapshotReader_h - -#include "jit/CompactBuffer.h" -#include "jit/IonCode.h" -#include "jit/IonTypes.h" -#include "jit/Registers.h" -#include "jit/Slot.h" - -namespace js { -namespace jit { - -#ifdef TRACK_SNAPSHOTS -class LInstruction; -#endif - -// A snapshot reader reads the entries out of the compressed snapshot buffer in -// a script. These entries describe the stack state of an Ion frame at a given -// position in JIT code. -class SnapshotReader -{ - CompactBufferReader reader_; - - uint32_t pcOffset_; // Offset from script->code. - uint32_t slotCount_; // Number of slots. - uint32_t frameCount_; - BailoutKind bailoutKind_; - uint32_t framesRead_; // Number of frame headers that have been read. - uint32_t slotsRead_; // Number of slots that have been read. - bool resumeAfter_; - -#ifdef TRACK_SNAPSHOTS - private: - uint32_t pcOpcode_; - uint32_t mirOpcode_; - uint32_t mirId_; - uint32_t lirOpcode_; - uint32_t lirId_; - public: - void spewBailingFrom() const; -#endif - - private: - - void readSnapshotHeader(); - void readFrameHeader(); - - public: - SnapshotReader(const uint8_t *buffer, const uint8_t *end); - - uint32_t pcOffset() const { - return pcOffset_; - } - uint32_t slots() const { - return slotCount_; - } - BailoutKind bailoutKind() const { - return bailoutKind_; - } - bool resumeAfter() const { - if (moreFrames()) - return false; - return resumeAfter_; - } - bool moreFrames() const { - return framesRead_ < frameCount_; - } - void nextFrame() { - readFrameHeader(); - } - Slot readSlot(); - - Value skip() { - readSlot(); - return UndefinedValue(); - } - - bool moreSlots() const { - return slotsRead_ < slotCount_; - } - uint32_t frameCount() const { - return frameCount_; - } -}; - -} -} - -#endif /* jit_SnapshotReader_h */ diff --git a/js/src/jit/SnapshotWriter.h b/js/src/jit/SnapshotWriter.h deleted file mode 100644 index a9f2248f2e95..000000000000 --- a/js/src/jit/SnapshotWriter.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef jit_SnapshotWriter_h -#define jit_SnapshotWriter_h - -#include "jit/Bailouts.h" -#include "jit/CompactBuffer.h" -#include "jit/Ion.h" -#include "jit/IonCode.h" -#include "jit/Registers.h" - -namespace js { -namespace jit { - -// Collects snapshots in a contiguous buffer, which is copied into IonScript -// memory after code generation. -class SnapshotWriter -{ - CompactBufferWriter writer_; - - // These are only used to assert sanity. - uint32_t nslots_; - uint32_t slotsWritten_; - uint32_t nframes_; - uint32_t framesWritten_; - SnapshotOffset lastStart_; - - void writeSlotHeader(JSValueType type, uint32_t regCode); - - public: - SnapshotOffset startSnapshot(uint32_t frameCount, BailoutKind kind, bool resumeAfter); - void startFrame(JSFunction *fun, JSScript *script, jsbytecode *pc, uint32_t exprStack); -#ifdef TRACK_SNAPSHOTS - void trackFrame(uint32_t pcOpcode, uint32_t mirOpcode, uint32_t mirId, - uint32_t lirOpcode, uint32_t lirId); -#endif - void endFrame(); - - void addSlot(const Slot &slot); - - void endSnapshot(); - - bool oom() const { - return writer_.oom() || writer_.length() >= MAX_BUFFER_SIZE; - } - - size_t size() const { - return writer_.length(); - } - const uint8_t *buffer() const { - return writer_.buffer(); - } -}; - -} -} - -#endif /* jit_SnapshotWriter_h */ diff --git a/js/src/jit/Snapshots.cpp b/js/src/jit/Snapshots.cpp index 7c68d02f58ef..1cdbf4d08118 100644 --- a/js/src/jit/Snapshots.cpp +++ b/js/src/jit/Snapshots.cpp @@ -4,15 +4,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "jit/Snapshots.h" + #include "jsscript.h" +#include "jit/CompileInfo.h" #include "jit/IonSpewer.h" #ifdef TRACK_SNAPSHOTS -#include "jit/LIR.h" -#include "jit/MIR.h" +# include "jit/LIR.h" +# include "jit/MIR.h" #endif -#include "jit/SnapshotReader.h" -#include "jit/SnapshotWriter.h" using namespace js; using namespace js::jit; @@ -28,15 +29,16 @@ using namespace js::jit; // [ptr] Debug only: JSScript * // [vwu] pc offset // [vwu] # of slots, including nargs -// [slot*] N slot entries, where N = nargs + nfixed + stackDepth +// [rva*] N recover value allocations entries, +// where N = nargs + nfixed + stackDepth // // Encodings: // [ptr] A fixed-size pointer. // [vwu] A variable-width unsigned integer. // [vws] A variable-width signed integer. // [u8] An 8-bit unsigned integer. -// [slot*] Information on how to reify a js::Value from an Ion frame. The -// first byte is split as thus: +// [rva*] list of RValueAllocation which are indicating how to find a js::Value +// on a call/bailout. The first byte is split as thus: // Bits 0-2: JSValueType // Bits 3-7: 5-bit register code ("reg"). // @@ -48,8 +50,8 @@ using namespace js::jit; // JSVAL_TYPE_OBJECT: // JSVAL_TYPE_BOOLEAN: // JSVAL_TYPE_STRING: -// If "reg" is InvalidReg1, this byte is followed by a [vws] -// stack offset. Otherwise, "reg" encodes a GPR register. +// If "reg" is ESC_REG_FIELD_INDEX, this byte is followed by a +// [vws] stack offset. Otherwise, "reg" encodes a GPR register. // // JSVAL_TYPE_NULL: // Reg value: @@ -86,17 +88,334 @@ using namespace js::jit; // code=3 reg, reg // // PUNBOX64: -// "reg" is InvalidReg1: byte is followed by a [vws] stack -// offset containing a Value. +// "reg" is ESC_REG_FIELD_INDEX: byte is followed by a [vws] +// stack offset containing a Value. // // Otherwise, "reg" is a register containing a Value. // +#ifdef JS_NUNBOX32 +static const uint32_t NUNBOX32_STACK_STACK = 0; +static const uint32_t NUNBOX32_STACK_REG = 1; +static const uint32_t NUNBOX32_REG_STACK = 2; +static const uint32_t NUNBOX32_REG_REG = 3; +#endif + +static const uint32_t MAX_TYPE_FIELD_VALUE = 7; + +static const uint32_t MAX_REG_FIELD_VALUE = 31; +static const uint32_t ESC_REG_FIELD_INDEX = 31; +static const uint32_t ESC_REG_FIELD_CONST = 30; +static const uint32_t ESC_REG_FIELD_FLOAT32_STACK = 29; +static const uint32_t ESC_REG_FIELD_FLOAT32_REG = 28; +static const uint32_t MIN_REG_FIELD_ESC = 28; + +RValueAllocation +RValueAllocation::read(CompactBufferReader &reader) +{ + uint8_t b = reader.readByte(); + + JSValueType type = JSValueType(b & 0x7); + uint32_t code = b >> 3; + + switch (type) { + case JSVAL_TYPE_DOUBLE: + if (code < MIN_REG_FIELD_ESC) + return Double(FloatRegister::FromCode(code)); + JS_ASSERT(code == ESC_REG_FIELD_INDEX); + return Typed(type, reader.readSigned()); + + case JSVAL_TYPE_INT32: + case JSVAL_TYPE_STRING: + case JSVAL_TYPE_OBJECT: + case JSVAL_TYPE_BOOLEAN: + if (code < MIN_REG_FIELD_ESC) + return Typed(type, Register::FromCode(code)); + JS_ASSERT(code == ESC_REG_FIELD_INDEX); + return Typed(type, reader.readSigned()); + + case JSVAL_TYPE_NULL: + if (code == ESC_REG_FIELD_CONST) + return Null(); + if (code == ESC_REG_FIELD_INDEX) + return Int32(reader.readSigned()); + if (code == ESC_REG_FIELD_FLOAT32_REG) + return Float32(FloatRegister::FromCode(reader.readUnsigned())); + if (code == ESC_REG_FIELD_FLOAT32_STACK) + return Float32(reader.readSigned()); + return Int32(code); + + case JSVAL_TYPE_UNDEFINED: + if (code == ESC_REG_FIELD_CONST) + return Undefined(); + if (code == ESC_REG_FIELD_INDEX) + return ConstantPool(reader.readUnsigned()); + return ConstantPool(code); + + case JSVAL_TYPE_MAGIC: + { + if (code == ESC_REG_FIELD_CONST) { + uint8_t reg2 = reader.readUnsigned(); + if (reg2 != ESC_REG_FIELD_INDEX) + return Typed(type, Register::FromCode(reg2)); + return Typed(type, reader.readSigned()); + } + +#ifdef JS_NUNBOX32 + int32_t type, payload; + switch (code) { + case NUNBOX32_STACK_STACK: + type = reader.readSigned(); + payload = reader.readSigned(); + return Untyped(type, payload); + case NUNBOX32_STACK_REG: + type = reader.readSigned(); + payload = reader.readByte(); + return Untyped(type, Register::FromCode(payload)); + case NUNBOX32_REG_STACK: + type = reader.readByte(); + payload = reader.readSigned(); + return Untyped(Register::FromCode(type), payload); + case NUNBOX32_REG_REG: + type = reader.readByte(); + payload = reader.readByte(); + return Untyped(Register::FromCode(type), + Register::FromCode(payload)); + default: + MOZ_ASSUME_UNREACHABLE("bad code"); + break; + } +#elif JS_PUNBOX64 + if (code < MIN_REG_FIELD_ESC) + return Untyped(Register::FromCode(code)); + JS_ASSERT(code == ESC_REG_FIELD_INDEX); + return Untyped(reader.readSigned()); +#endif + } + + default: + MOZ_ASSUME_UNREACHABLE("bad type"); + break; + } + + MOZ_ASSUME_UNREACHABLE("huh?"); +} + +void +RValueAllocation::writeHeader(CompactBufferWriter &writer, + JSValueType type, + uint32_t regCode) const +{ + JS_ASSERT(uint32_t(type) <= MAX_TYPE_FIELD_VALUE); + JS_ASSERT(uint32_t(regCode) <= MAX_REG_FIELD_VALUE); + JS_STATIC_ASSERT(Registers::Total < MIN_REG_FIELD_ESC); + + uint8_t byte = uint32_t(type) | (regCode << 3); + writer.writeByte(byte); +} + +void +RValueAllocation::write(CompactBufferWriter &writer) const +{ + switch (mode()) { + case CONSTANT: { + if (constantIndex() < MIN_REG_FIELD_ESC) { + writeHeader(writer, JSVAL_TYPE_UNDEFINED, constantIndex()); + } else { + writeHeader(writer, JSVAL_TYPE_UNDEFINED, ESC_REG_FIELD_INDEX); + writer.writeUnsigned(constantIndex()); + } + break; + } + + case DOUBLE_REG: { + writeHeader(writer, JSVAL_TYPE_DOUBLE, floatReg().code()); + break; + } + + case FLOAT32_REG: { + writeHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_FLOAT32_REG); + writer.writeUnsigned(floatReg().code()); + break; + } + + case FLOAT32_STACK: { + writeHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_FLOAT32_STACK); + writer.writeSigned(stackOffset()); + break; + } + + case TYPED_REG: { + writeHeader(writer, knownType(), reg().code()); + break; + } + case TYPED_STACK: { + writeHeader(writer, knownType(), ESC_REG_FIELD_INDEX); + writer.writeSigned(stackOffset()); + break; + } +#if defined(JS_NUNBOX32) + case UNTYPED_REG_REG: { + writeHeader(writer, JSVAL_TYPE_MAGIC, NUNBOX32_REG_REG); + writer.writeByte(type().reg().code()); + writer.writeByte(payload().reg().code()); + break; + } + case UNTYPED_REG_STACK: { + writeHeader(writer, JSVAL_TYPE_MAGIC, NUNBOX32_REG_STACK); + writer.writeByte(type().reg().code()); + writer.writeSigned(payload().stackOffset()); + break; + } + case UNTYPED_STACK_REG: { + writeHeader(writer, JSVAL_TYPE_MAGIC, NUNBOX32_STACK_REG); + writer.writeSigned(type().stackOffset()); + writer.writeByte(payload().reg().code()); + break; + } + case UNTYPED_STACK_STACK: { + writeHeader(writer, JSVAL_TYPE_MAGIC, NUNBOX32_STACK_STACK); + writer.writeSigned(type().stackOffset()); + writer.writeSigned(payload().stackOffset()); + break; + } +#elif defined(JS_PUNBOX64) + case UNTYPED_REG: { + writeHeader(writer, JSVAL_TYPE_MAGIC, value().reg().code()); + break; + } + case UNTYPED_STACK: { + writeHeader(writer, JSVAL_TYPE_MAGIC, ESC_REG_FIELD_INDEX); + writer.writeSigned(value().stackOffset()); + break; + } +#endif + case JS_UNDEFINED: { + writeHeader(writer, JSVAL_TYPE_UNDEFINED, ESC_REG_FIELD_CONST); + break; + } + case JS_NULL: { + writeHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_CONST); + break; + } + case JS_INT32: { + if (int32Value() >= 0 && uint32_t(int32Value()) < MIN_REG_FIELD_ESC) { + writeHeader(writer, JSVAL_TYPE_NULL, int32Value()); + } else { + writeHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_INDEX); + writer.writeSigned(int32Value()); + } + break; + } + case INVALID: { + MOZ_ASSUME_UNREACHABLE("not initialized"); + break; + } + } +} + +void +Location::dump(FILE *fp) const +{ + if (isStackOffset()) + fprintf(fp, "stack %d", stackOffset()); + else + fprintf(fp, "reg %s", reg().name()); +} + +static const char * +ValTypeToString(JSValueType type) +{ + switch (type) { + case JSVAL_TYPE_INT32: + return "int32_t"; + case JSVAL_TYPE_DOUBLE: + return "double"; + case JSVAL_TYPE_STRING: + return "string"; + case JSVAL_TYPE_BOOLEAN: + return "boolean"; + case JSVAL_TYPE_OBJECT: + return "object"; + case JSVAL_TYPE_MAGIC: + return "magic"; + default: + MOZ_ASSUME_UNREACHABLE("no payload"); + } +} + +void +RValueAllocation::dump(FILE *fp) const +{ + switch (mode()) { + case CONSTANT: + fprintf(fp, "constant (pool index %u)", constantIndex()); + break; + + case DOUBLE_REG: + fprintf(fp, "double (reg %s)", floatReg().name()); + break; + + case FLOAT32_REG: + fprintf(fp, "float32 (reg %s)", floatReg().name()); + break; + + case FLOAT32_STACK: + fprintf(fp, "float32 ("); + known_type_.payload.dump(fp); + fprintf(fp, ")"); + break; + + case TYPED_REG: + case TYPED_STACK: + fprintf(fp, "%s (", ValTypeToString(knownType())); + known_type_.payload.dump(fp); + fprintf(fp, ")"); + break; + +#if defined(JS_NUNBOX32) + case UNTYPED_REG_REG: + case UNTYPED_REG_STACK: + case UNTYPED_STACK_REG: + case UNTYPED_STACK_STACK: + fprintf(fp, "value (type = "); + type().dump(fp); + fprintf(fp, ", payload = "); + payload().dump(fp); + fprintf(fp, ")"); + break; +#elif defined(JS_PUNBOX64) + case UNTYPED_REG: + case UNTYPED_STACK: + fprintf(fp, "value ("); + value().dump(fp); + fprintf(fp, ")"); + break; +#endif + + case JS_UNDEFINED: + fprintf(fp, "undefined"); + break; + + case JS_NULL: + fprintf(fp, "null"); + break; + + case JS_INT32: + fprintf(fp, "int32_t %d", int32Value()); + break; + + case INVALID: + fprintf(fp, "invalid"); + break; + } +} + SnapshotReader::SnapshotReader(const uint8_t *buffer, const uint8_t *end) : reader_(buffer, end), - slotCount_(0), + allocCount_(0), frameCount_(0), - slotsRead_(0) + allocRead_(0) { if (!buffer) return; @@ -129,12 +448,10 @@ void SnapshotReader::readFrameHeader() { JS_ASSERT(moreFrames()); - JS_ASSERT(slotsRead_ == slotCount_); + JS_ASSERT(allocRead_ == allocCount_); pcOffset_ = reader_.readUnsigned(); - slotCount_ = reader_.readUnsigned(); - IonSpew(IonSpew_Snapshots, "Read pc offset %u, nslots %u", pcOffset_, slotCount_); - + allocCount_ = reader_.readUnsigned(); #ifdef TRACK_SNAPSHOTS pcOpcode_ = reader_.readUnsigned(); mirOpcode_ = reader_.readUnsigned(); @@ -142,9 +459,10 @@ SnapshotReader::readFrameHeader() lirOpcode_ = reader_.readUnsigned(); lirId_ = reader_.readUnsigned(); #endif + IonSpew(IonSpew_Snapshots, "Read pc offset %u, nslots %u", pcOffset_, allocCount_); framesRead_++; - slotsRead_ = 0; + allocRead_ = 0; } #ifdef TRACK_SNAPSHOTS @@ -163,13 +481,13 @@ SnapshotReader::spewBailingFrom() const } #endif -Slot -SnapshotReader::readSlot() +RValueAllocation +SnapshotReader::readAllocation() { - JS_ASSERT(slotsRead_ < slotCount_); - IonSpew(IonSpew_Snapshots, "Reading slot %u", slotsRead_); - slotsRead_++; - return Slot::read(reader_); + JS_ASSERT(allocRead_ < allocCount_); + IonSpew(IonSpew_Snapshots, "Reading slot %u", allocRead_); + allocRead_++; + return RValueAllocation::read(reader_); } SnapshotOffset @@ -206,16 +524,16 @@ SnapshotWriter::startFrame(JSFunction *fun, JSScript *script, jsbytecode *pc, ui uint32_t implicit = StartArgSlot(script); uint32_t formalArgs = CountArgSlots(script, fun); - nslots_ = formalArgs + script->nfixed() + exprStack; - slotsWritten_ = 0; + nallocs_ = formalArgs + script->nfixed() + exprStack; + allocWritten_ = 0; IonSpew(IonSpew_Snapshots, "Starting frame; implicit %u, formals %u, fixed %u, exprs %u", implicit, formalArgs - implicit, script->nfixed(), exprStack); uint32_t pcoff = script->pcToOffset(pc); - IonSpew(IonSpew_Snapshots, "Writing pc offset %u, nslots %u", pcoff, nslots_); + IonSpew(IonSpew_Snapshots, "Writing pc offset %u, nslots %u", pcoff, nallocs_); writer_.writeUnsigned(pcoff); - writer_.writeUnsigned(nslots_); + writer_.writeUnsigned(nallocs_); } #ifdef TRACK_SNAPSHOTS @@ -232,26 +550,26 @@ SnapshotWriter::trackFrame(uint32_t pcOpcode, uint32_t mirOpcode, uint32_t mirId #endif void -SnapshotWriter::addSlot(const Slot &slot) +SnapshotWriter::add(const RValueAllocation &alloc) { if (IonSpewEnabled(IonSpew_Snapshots)) { IonSpewHeader(IonSpew_Snapshots); - fprintf(IonSpewFile, " slot %u: ", slotsWritten_); - slot.dump(IonSpewFile); + fprintf(IonSpewFile, " slot %u: ", allocWritten_); + alloc.dump(IonSpewFile); fprintf(IonSpewFile, "\n"); } - slotsWritten_++; - JS_ASSERT(slotsWritten_ <= nslots_); - slot.write(writer_); + allocWritten_++; + JS_ASSERT(allocWritten_ <= nallocs_); + alloc.write(writer_); } void SnapshotWriter::endFrame() { // Check that the last write succeeded. - JS_ASSERT(nslots_ == slotsWritten_); - nslots_ = slotsWritten_ = 0; + JS_ASSERT(nallocs_ == allocWritten_); + nallocs_ = allocWritten_ = 0; framesWritten_++; } diff --git a/js/src/jit/Slot.h b/js/src/jit/Snapshots.h similarity index 54% rename from js/src/jit/Slot.h rename to js/src/jit/Snapshots.h index d760fab09b4f..02ed12e9b6c8 100644 --- a/js/src/jit/Slot.h +++ b/js/src/jit/Snapshots.h @@ -4,65 +4,73 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef jit_Slot_h -#define jit_Slot_h +#ifndef jit_Snapshot_h +#define jit_Snapshot_h +#include "jsbytecode.h" + +#include "jit/CompactBuffer.h" +#include "jit/IonTypes.h" #include "jit/Registers.h" namespace js { namespace jit { -class CompactBufferReader; -class CompactBufferWriter; - -class Slot; +class RValueAllocation; class Location { - friend class Slot; + friend class RValueAllocation; // An offset that is illegal for a local variable's stack allocation. - static const int32_t InvalidStackSlot = -1; + static const int32_t InvalidStackOffset = -1; Register::Code reg_; - int32_t stackSlot_; + int32_t stackOffset_; static Location From(const Register ®) { Location loc; loc.reg_ = reg.code(); - loc.stackSlot_ = InvalidStackSlot; + loc.stackOffset_ = InvalidStackOffset; return loc; } - static Location From(int32_t stackSlot) { - JS_ASSERT(stackSlot != InvalidStackSlot); + static Location From(int32_t stackOffset) { + JS_ASSERT(stackOffset != InvalidStackOffset); Location loc; loc.reg_ = Register::Code(0); // Quell compiler warnings. - loc.stackSlot_ = stackSlot; + loc.stackOffset_ = stackOffset; return loc; } public: Register reg() const { - JS_ASSERT(!isStackSlot()); + JS_ASSERT(!isStackOffset()); return Register::FromCode(reg_); } - int32_t stackSlot() const { - JS_ASSERT(isStackSlot()); - return stackSlot_; + int32_t stackOffset() const { + JS_ASSERT(isStackOffset()); + return stackOffset_; } - bool isStackSlot() const { - return stackSlot_ != InvalidStackSlot; + bool isStackOffset() const { + return stackOffset_ != InvalidStackOffset; } void dump(FILE *fp) const; public: bool operator==(const Location &l) const { - return reg_ == l.reg_ && stackSlot_ == l.stackSlot_; + return reg_ == l.reg_ && stackOffset_ == l.stackOffset_; } }; -class Slot +// A Recover Value Allocation mirror what is known at compiled time as being the +// MIRType and the LAllocation. This is read out of the snapshot to recover the +// value which would be there if this frame was an interpreter frame instead of +// an Ion frame. +// +// It is used with the SnapshotIterator to recover a Value from the stack, +// spilled registers or the list of constant of the compiled script. +class RValueAllocation { public: enum Mode @@ -130,32 +138,32 @@ class Slot int32_t value_; }; - Slot(Mode mode, JSValueType type, const Location &loc) + RValueAllocation(Mode mode, JSValueType type, const Location &loc) : mode_(mode) { JS_ASSERT(mode == TYPED_REG || mode == TYPED_STACK); known_type_.type = type; known_type_.payload = loc; } - Slot(Mode mode, const FloatRegister ®) + RValueAllocation(Mode mode, const FloatRegister ®) : mode_(mode) { JS_ASSERT(mode == FLOAT32_REG || mode == DOUBLE_REG); fpu_ = reg.code(); } - Slot(Mode mode, const Location &loc) + RValueAllocation(Mode mode, const Location &loc) : mode_(mode) { JS_ASSERT(mode == FLOAT32_STACK); known_type_.payload = loc; } - Slot(Mode mode, int32_t index) + RValueAllocation(Mode mode, int32_t index) : mode_(mode) { JS_ASSERT(mode == CONSTANT || mode == JS_INT32); value_ = index; } - Slot(Mode mode) + RValueAllocation(Mode mode) : mode_(mode) { JS_ASSERT(mode == JS_UNDEFINED || mode == JS_NULL || @@ -163,103 +171,103 @@ class Slot } public: - Slot() + RValueAllocation() : mode_(INVALID) { } // DOUBLE_REG - static Slot DoubleSlot(const FloatRegister ®) { - return Slot(DOUBLE_REG, reg); + static RValueAllocation Double(const FloatRegister ®) { + return RValueAllocation(DOUBLE_REG, reg); } // FLOAT32_REG or FLOAT32_STACK - static Slot Float32Slot(const FloatRegister ®) { - return Slot(FLOAT32_REG, reg); + static RValueAllocation Float32(const FloatRegister ®) { + return RValueAllocation(FLOAT32_REG, reg); } - static Slot Float32Slot(int32_t stackIndex) { - return Slot(FLOAT32_STACK, Location::From(stackIndex)); + static RValueAllocation Float32(int32_t stackIndex) { + return RValueAllocation(FLOAT32_STACK, Location::From(stackIndex)); } // TYPED_REG or TYPED_STACK - static Slot TypedSlot(JSValueType type, const Register ®) { + static RValueAllocation Typed(JSValueType type, const Register ®) { JS_ASSERT(type != JSVAL_TYPE_DOUBLE && type != JSVAL_TYPE_MAGIC && type != JSVAL_TYPE_NULL && type != JSVAL_TYPE_UNDEFINED); - return Slot(TYPED_REG, type, Location::From(reg)); + return RValueAllocation(TYPED_REG, type, Location::From(reg)); } - static Slot TypedSlot(JSValueType type, int32_t stackIndex) { + static RValueAllocation Typed(JSValueType type, int32_t stackIndex) { JS_ASSERT(type != JSVAL_TYPE_MAGIC && type != JSVAL_TYPE_NULL && type != JSVAL_TYPE_UNDEFINED); - return Slot(TYPED_STACK, type, Location::From(stackIndex)); + return RValueAllocation(TYPED_STACK, type, Location::From(stackIndex)); } // UNTYPED #if defined(JS_NUNBOX32) - static Slot UntypedSlot(const Register &type, const Register &payload) { - Slot slot(UNTYPED_REG_REG); + static RValueAllocation Untyped(const Register &type, const Register &payload) { + RValueAllocation slot(UNTYPED_REG_REG); slot.unknown_type_.type = Location::From(type); slot.unknown_type_.payload = Location::From(payload); return slot; } - static Slot UntypedSlot(const Register &type, int32_t payloadStackIndex) { - Slot slot(UNTYPED_REG_STACK); + static RValueAllocation Untyped(const Register &type, int32_t payloadStackIndex) { + RValueAllocation slot(UNTYPED_REG_STACK); slot.unknown_type_.type = Location::From(type); slot.unknown_type_.payload = Location::From(payloadStackIndex); return slot; } - static Slot UntypedSlot(int32_t typeStackIndex, const Register &payload) { - Slot slot(UNTYPED_STACK_REG); + static RValueAllocation Untyped(int32_t typeStackIndex, const Register &payload) { + RValueAllocation slot(UNTYPED_STACK_REG); slot.unknown_type_.type = Location::From(typeStackIndex); slot.unknown_type_.payload = Location::From(payload); return slot; } - static Slot UntypedSlot(int32_t typeStackIndex, int32_t payloadStackIndex) { - Slot slot(UNTYPED_STACK_STACK); + static RValueAllocation Untyped(int32_t typeStackIndex, int32_t payloadStackIndex) { + RValueAllocation slot(UNTYPED_STACK_STACK); slot.unknown_type_.type = Location::From(typeStackIndex); slot.unknown_type_.payload = Location::From(payloadStackIndex); return slot; } #elif defined(JS_PUNBOX64) - static Slot UntypedSlot(const Register &value) { - Slot slot(UNTYPED_REG); + static RValueAllocation Untyped(const Register &value) { + RValueAllocation slot(UNTYPED_REG); slot.unknown_type_.value = Location::From(value); return slot; } - static Slot UntypedSlot(int32_t valueStackSlot) { - Slot slot(UNTYPED_STACK); - slot.unknown_type_.value = Location::From(valueStackSlot); + static RValueAllocation Untyped(int32_t stackOffset) { + RValueAllocation slot(UNTYPED_STACK); + slot.unknown_type_.value = Location::From(stackOffset); return slot; } #endif // common constants. - static Slot UndefinedSlot() { - return Slot(JS_UNDEFINED); + static RValueAllocation Undefined() { + return RValueAllocation(JS_UNDEFINED); } - static Slot NullSlot() { - return Slot(JS_NULL); + static RValueAllocation Null() { + return RValueAllocation(JS_NULL); } // JS_INT32 - static Slot Int32Slot(int32_t value) { - return Slot(JS_INT32, value); + static RValueAllocation Int32(int32_t value) { + return RValueAllocation(JS_INT32, value); } // CONSTANT's index - static Slot ConstantPoolSlot(uint32_t index) { - return Slot(CONSTANT, int32_t(index)); + static RValueAllocation ConstantPool(uint32_t index) { + return RValueAllocation(CONSTANT, int32_t(index)); } - void writeSlotHeader(CompactBufferWriter &writer, JSValueType type, uint32_t regCode) const; + void writeHeader(CompactBufferWriter &writer, JSValueType type, uint32_t regCode) const; public: - static Slot read(CompactBufferReader &reader); + static RValueAllocation read(CompactBufferReader &reader); void write(CompactBufferWriter &writer) const; public: @@ -286,9 +294,9 @@ class Slot JS_ASSERT(mode() == DOUBLE_REG || mode() == FLOAT32_REG); return FloatRegister::FromCode(fpu_); } - int32_t stackSlot() const { + int32_t stackOffset() const { JS_ASSERT(mode() == TYPED_STACK || mode() == FLOAT32_STACK); - return known_type_.payload.stackSlot(); + return known_type_.payload.stackOffset(); } #if defined(JS_NUNBOX32) Location payload() const { @@ -312,7 +320,7 @@ class Slot void dump() const; public: - bool operator==(const Slot &s) const { + bool operator==(const RValueAllocation &s) const { if (mode_ != s.mode_) return false; @@ -346,7 +354,110 @@ class Slot } }; +// Collects snapshots in a contiguous buffer, which is copied into IonScript +// memory after code generation. +class SnapshotWriter +{ + CompactBufferWriter writer_; + + // These are only used to assert sanity. + uint32_t nallocs_; + uint32_t allocWritten_; + uint32_t nframes_; + uint32_t framesWritten_; + SnapshotOffset lastStart_; + + public: + SnapshotOffset startSnapshot(uint32_t frameCount, BailoutKind kind, bool resumeAfter); + void startFrame(JSFunction *fun, JSScript *script, jsbytecode *pc, uint32_t exprStack); +#ifdef TRACK_SNAPSHOTS + void trackFrame(uint32_t pcOpcode, uint32_t mirOpcode, uint32_t mirId, + uint32_t lirOpcode, uint32_t lirId); +#endif + void endFrame(); + + void add(const RValueAllocation &slot); + + void endSnapshot(); + + bool oom() const { + return writer_.oom() || writer_.length() >= MAX_BUFFER_SIZE; + } + + size_t size() const { + return writer_.length(); + } + const uint8_t *buffer() const { + return writer_.buffer(); + } +}; + +// A snapshot reader reads the entries out of the compressed snapshot buffer in +// a script. These entries describe the equivalent interpreter frames at a given +// position in JIT code. Each entry is an Ion's value allocations, used to +// recover the corresponding Value from an Ion frame. +class SnapshotReader +{ + CompactBufferReader reader_; + + uint32_t pcOffset_; // Offset from script->code. + uint32_t allocCount_; // Number of slots. + uint32_t frameCount_; + BailoutKind bailoutKind_; + uint32_t framesRead_; // Number of frame headers that have been read. + uint32_t allocRead_; // Number of slots that have been read. + bool resumeAfter_; + +#ifdef TRACK_SNAPSHOTS + private: + uint32_t pcOpcode_; + uint32_t mirOpcode_; + uint32_t mirId_; + uint32_t lirOpcode_; + uint32_t lirId_; + + public: + void spewBailingFrom() const; +#endif + + private: + void readSnapshotHeader(); + void readFrameHeader(); + + public: + SnapshotReader(const uint8_t *buffer, const uint8_t *end); + + uint32_t pcOffset() const { + return pcOffset_; + } + uint32_t allocations() const { + return allocCount_; + } + BailoutKind bailoutKind() const { + return bailoutKind_; + } + bool resumeAfter() const { + if (moreFrames()) + return false; + return resumeAfter_; + } + bool moreFrames() const { + return framesRead_ < frameCount_; + } + void nextFrame() { + readFrameHeader(); + } + RValueAllocation readAllocation(); + + bool moreAllocations() const { + return allocRead_ < allocCount_; + } + uint32_t frameCount() const { + return frameCount_; + } +}; + } } -#endif // jit_Slot_h +#endif /* jit_Snapshot_h */ diff --git a/js/src/jit/shared/CodeGenerator-shared.cpp b/js/src/jit/shared/CodeGenerator-shared.cpp index e42f93a2deb9..ad506873a449 100644 --- a/js/src/jit/shared/CodeGenerator-shared.cpp +++ b/js/src/jit/shared/CodeGenerator-shared.cpp @@ -131,14 +131,14 @@ ToStackIndex(LAllocation *a) } bool -CodeGeneratorShared::encodeSlots(LSnapshot *snapshot, MResumePoint *resumePoint, - uint32_t *startIndex) +CodeGeneratorShared::encodeAllocations(LSnapshot *snapshot, MResumePoint *resumePoint, + uint32_t *startIndex) { IonSpew(IonSpew_Codegen, "Encoding %u of resume point %p's operands starting from %u", resumePoint->numOperands(), (void *) resumePoint, *startIndex); - for (uint32_t slotno = 0, e = resumePoint->numOperands(); slotno < e; slotno++) { - uint32_t i = slotno + *startIndex; - MDefinition *mir = resumePoint->getOperand(slotno); + for (uint32_t allocno = 0, e = resumePoint->numOperands(); allocno < e; allocno++) { + uint32_t i = allocno + *startIndex; + MDefinition *mir = resumePoint->getOperand(allocno); if (mir->isBox()) mir = mir->toBox()->getOperand(0); @@ -147,14 +147,14 @@ CodeGeneratorShared::encodeSlots(LSnapshot *snapshot, MResumePoint *resumePoint, ? MIRType_Undefined : mir->type(); - Slot s; + RValueAllocation alloc; switch (type) { case MIRType_Undefined: - s = Slot::UndefinedSlot(); + alloc = RValueAllocation::Undefined(); break; case MIRType_Null: - s = Slot::NullSlot(); + alloc = RValueAllocation::Null(); break; case MIRType_Int32: case MIRType_String: @@ -167,29 +167,29 @@ CodeGeneratorShared::encodeSlots(LSnapshot *snapshot, MResumePoint *resumePoint, JSValueType valueType = ValueTypeFromMIRType(type); if (payload->isMemory()) { if (type == MIRType_Float32) - s = Slot::Float32Slot(ToStackIndex(payload)); + alloc = RValueAllocation::Float32(ToStackIndex(payload)); else - s = Slot::TypedSlot(valueType, ToStackIndex(payload)); + alloc = RValueAllocation::Typed(valueType, ToStackIndex(payload)); } else if (payload->isGeneralReg()) { - s = Slot::TypedSlot(valueType, ToRegister(payload)); + alloc = RValueAllocation::Typed(valueType, ToRegister(payload)); } else if (payload->isFloatReg()) { FloatRegister reg = ToFloatRegister(payload); if (type == MIRType_Float32) - s = Slot::Float32Slot(reg); + alloc = RValueAllocation::Float32(reg); else - s = Slot::DoubleSlot(reg); + alloc = RValueAllocation::Double(reg); } else { MConstant *constant = mir->toConstant(); const Value &v = constant->value(); // Don't bother with the constant pool for smallish integers. if (v.isInt32() && v.toInt32() >= -32 && v.toInt32() <= 32) { - s = Slot::Int32Slot(v.toInt32()); + alloc = RValueAllocation::Int32(v.toInt32()); } else { uint32_t index; if (!graph.addConstantToPool(constant->value(), &index)) return false; - s = Slot::ConstantPoolSlot(index); + alloc = RValueAllocation::ConstantPool(index); } } break; @@ -199,7 +199,7 @@ CodeGeneratorShared::encodeSlots(LSnapshot *snapshot, MResumePoint *resumePoint, uint32_t index; if (!graph.addConstantToPool(MagicValue(JS_OPTIMIZED_ARGUMENTS), &index)) return false; - s = Slot::ConstantPoolSlot(index); + alloc = RValueAllocation::ConstantPool(index); break; } default: @@ -210,26 +210,26 @@ CodeGeneratorShared::encodeSlots(LSnapshot *snapshot, MResumePoint *resumePoint, LAllocation *type = snapshot->typeOfSlot(i); if (type->isRegister()) { if (payload->isRegister()) - s = Slot::UntypedSlot(ToRegister(type), ToRegister(payload)); + alloc = RValueAllocation::Untyped(ToRegister(type), ToRegister(payload)); else - s = Slot::UntypedSlot(ToRegister(type), ToStackIndex(payload)); + alloc = RValueAllocation::Untyped(ToRegister(type), ToStackIndex(payload)); } else { if (payload->isRegister()) - s = Slot::UntypedSlot(ToStackIndex(type), ToRegister(payload)); + alloc = RValueAllocation::Untyped(ToStackIndex(type), ToRegister(payload)); else - s = Slot::UntypedSlot(ToStackIndex(type), ToStackIndex(payload)); + alloc = RValueAllocation::Untyped(ToStackIndex(type), ToStackIndex(payload)); } #elif JS_PUNBOX64 if (payload->isRegister()) - s = Slot::UntypedSlot(ToRegister(payload)); + alloc = RValueAllocation::Untyped(ToRegister(payload)); else - s = Slot::UntypedSlot(ToStackIndex(payload)); + alloc = RValueAllocation::Untyped(ToStackIndex(payload)); #endif break; } } - snapshots_.addSlot(s); + snapshots_.add(alloc); } *startIndex += resumePoint->numOperands(); @@ -332,7 +332,7 @@ CodeGeneratorShared::encode(LSnapshot *snapshot) snapshots_.trackFrame(pcOpcode, mirOpcode, mirId, lirOpcode, lirId); #endif - if (!encodeSlots(snapshot, mir, &startIndex)) + if (!encodeAllocations(snapshot, mir, &startIndex)) return false; snapshots_.endFrame(); } diff --git a/js/src/jit/shared/CodeGenerator-shared.h b/js/src/jit/shared/CodeGenerator-shared.h index 149a6965503b..55a95563be6a 100644 --- a/js/src/jit/shared/CodeGenerator-shared.h +++ b/js/src/jit/shared/CodeGenerator-shared.h @@ -15,7 +15,7 @@ #include "jit/MIRGenerator.h" #include "jit/MIRGraph.h" #include "jit/Safepoints.h" -#include "jit/SnapshotWriter.h" +#include "jit/Snapshots.h" #include "jit/VMFunctions.h" #include "vm/ForkJoin.h" @@ -258,7 +258,7 @@ class CodeGeneratorShared : public LInstructionVisitor // Encodes an LSnapshot into the compressed snapshot buffer, returning // false on failure. bool encode(LSnapshot *snapshot); - bool encodeSlots(LSnapshot *snapshot, MResumePoint *resumePoint, uint32_t *startIndex); + bool encodeAllocations(LSnapshot *snapshot, MResumePoint *resumePoint, uint32_t *startIndex); // Attempts to assign a BailoutId to a snapshot, if one isn't already set. // If the bailout table is full, this returns false, which is not a fatal diff --git a/js/src/jsapi-tests/moz.build b/js/src/jsapi-tests/moz.build index 5d363d42e263..4bd7d131dbb5 100644 --- a/js/src/jsapi-tests/moz.build +++ b/js/src/jsapi-tests/moz.build @@ -41,7 +41,7 @@ UNIFIED_SOURCES += [ 'testIntern.cpp', 'testIntString.cpp', 'testIntTypesABI.cpp', - 'testJitSlot.cpp', + 'testJitRValueAlloc.cpp', 'testJSEvaluateScript.cpp', 'testLookup.cpp', 'testLooselyEqual.cpp', diff --git a/js/src/jsapi-tests/testJitSlot.cpp b/js/src/jsapi-tests/testJitRValueAlloc.cpp similarity index 53% rename from js/src/jsapi-tests/testJitSlot.cpp rename to js/src/jsapi-tests/testJitRValueAlloc.cpp index c103da392b41..fa9bae1da65a 100644 --- a/js/src/jsapi-tests/testJitSlot.cpp +++ b/js/src/jsapi-tests/testJitRValueAlloc.cpp @@ -5,8 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "jit/CompactBuffer.h" -#include "jit/Slot.h" +#include "jit/Snapshots.h" #include "jsapi-tests/tests.h" @@ -16,53 +15,53 @@ using namespace js::jit; // These tests are checking that all slots of the current architecture can all // be encoded and decoded correctly. We iterate on all registers and on many // fake stack locations (Fibonacci). -static Slot -ReadSlot(const Slot &slot) +static RValueAllocation +Read(const RValueAllocation &slot) { CompactBufferWriter writer; slot.write(writer); CompactBufferReader reader(writer); - return Slot::read(reader); + return RValueAllocation::read(reader); } -BEGIN_TEST(testJitSlot_Double) +BEGIN_TEST(testJitRValueAlloc_Double) { - Slot s; + RValueAllocation s; for (uint32_t i = 0; i < FloatRegisters::Total; i++) { - s = Slot::DoubleSlot(FloatRegister::FromCode(i)); - CHECK(s == ReadSlot(s)); + s = RValueAllocation::Double(FloatRegister::FromCode(i)); + CHECK(s == Read(s)); } return true; } -END_TEST(testJitSlot_Double) +END_TEST(testJitRValueAlloc_Double) -BEGIN_TEST(testJitSlot_FloatReg) +BEGIN_TEST(testJitRValueAlloc_FloatReg) { - Slot s; + RValueAllocation s; for (uint32_t i = 0; i < FloatRegisters::Total; i++) { - s = Slot::Float32Slot(FloatRegister::FromCode(i)); - CHECK(s == ReadSlot(s)); + s = RValueAllocation::Float32(FloatRegister::FromCode(i)); + CHECK(s == Read(s)); } return true; } -END_TEST(testJitSlot_FloatReg) +END_TEST(testJitRValueAlloc_FloatReg) -BEGIN_TEST(testJitSlot_FloatStack) +BEGIN_TEST(testJitRValueAlloc_FloatStack) { - Slot s; + RValueAllocation s; int32_t i, last = 0, tmp; for (i = 0; i > 0; tmp = i, i += last, last = tmp) { - s = Slot::Float32Slot(i); - CHECK(s == ReadSlot(s)); + s = RValueAllocation::Float32(i); + CHECK(s == Read(s)); } return true; } -END_TEST(testJitSlot_FloatStack) +END_TEST(testJitRValueAlloc_FloatStack) -BEGIN_TEST(testJitSlot_TypedReg) +BEGIN_TEST(testJitRValueAlloc_TypedReg) { - Slot s; + RValueAllocation s; for (uint32_t i = 0; i < Registers::Total; i++) { #define FOR_EACH_JSVAL(_) \ /* _(JSVAL_TYPE_DOUBLE) */ \ @@ -74,9 +73,9 @@ BEGIN_TEST(testJitSlot_TypedReg) /* _(JSVAL_TYPE_NULL) */ \ _(JSVAL_TYPE_OBJECT) -#define CHECK_WITH_JSVAL(jsval) \ - s = Slot::TypedSlot(jsval, Register::FromCode(i)); \ - CHECK(s == ReadSlot(s)); +#define CHECK_WITH_JSVAL(jsval) \ + s = RValueAllocation::Typed(jsval, Register::FromCode(i)); \ + CHECK(s == Read(s)); FOR_EACH_JSVAL(CHECK_WITH_JSVAL) #undef CHECK_WITH_JSVAL @@ -84,11 +83,11 @@ BEGIN_TEST(testJitSlot_TypedReg) } return true; } -END_TEST(testJitSlot_TypedReg) +END_TEST(testJitRValueAlloc_TypedReg) -BEGIN_TEST(testJitSlot_TypedStack) +BEGIN_TEST(testJitRValueAlloc_TypedStack) { - Slot s; + RValueAllocation s; int32_t i, last = 0, tmp; for (i = 0; i > 0; tmp = i, i += last, last = tmp) { #define FOR_EACH_JSVAL(_) \ @@ -101,9 +100,9 @@ BEGIN_TEST(testJitSlot_TypedStack) /* _(JSVAL_TYPE_NULL) */ \ _(JSVAL_TYPE_OBJECT) -#define CHECK_WITH_JSVAL(jsval) \ - s = Slot::TypedSlot(jsval, i); \ - CHECK(s == ReadSlot(s)); +#define CHECK_WITH_JSVAL(jsval) \ + s = RValueAllocation::Typed(jsval, i); \ + CHECK(s == Read(s)); FOR_EACH_JSVAL(CHECK_WITH_JSVAL) #undef CHECK_WITH_JSVAL @@ -111,127 +110,127 @@ BEGIN_TEST(testJitSlot_TypedStack) } return true; } -END_TEST(testJitSlot_TypedStack) +END_TEST(testJitRValueAlloc_TypedStack) #if defined(JS_NUNBOX32) -BEGIN_TEST(testJitSlot_UntypedRegReg) +BEGIN_TEST(testJitRValueAlloc_UntypedRegReg) { - Slot s; + RValueAllocation s; for (uint32_t i = 0; i < Registers::Total; i++) { for (uint32_t j = 0; j < Registers::Total; j++) { if (i == j) continue; - s = Slot::UntypedSlot(Register::FromCode(i), Register::FromCode(j)); - MOZ_ASSERT(s == ReadSlot(s)); - CHECK(s == ReadSlot(s)); + s = RValueAllocation::Untyped(Register::FromCode(i), Register::FromCode(j)); + MOZ_ASSERT(s == Read(s)); + CHECK(s == Read(s)); } } return true; } -END_TEST(testJitSlot_UntypedRegReg) +END_TEST(testJitRValueAlloc_UntypedRegReg) -BEGIN_TEST(testJitSlot_UntypedRegStack) +BEGIN_TEST(testJitRValueAlloc_UntypedRegStack) { - Slot s; + RValueAllocation s; for (uint32_t i = 0; i < Registers::Total; i++) { int32_t j, last = 0, tmp; for (j = 0; j > 0; tmp = j, j += last, last = tmp) { - s = Slot::UntypedSlot(Register::FromCode(i), j); - CHECK(s == ReadSlot(s)); + s = RValueAllocation::Untyped(Register::FromCode(i), j); + CHECK(s == Read(s)); } } return true; } -END_TEST(testJitSlot_UntypedRegStack) +END_TEST(testJitRValueAlloc_UntypedRegStack) -BEGIN_TEST(testJitSlot_UntypedStackReg) +BEGIN_TEST(testJitRValueAlloc_UntypedStackReg) { - Slot s; + RValueAllocation s; int32_t i, last = 0, tmp; for (i = 0; i > 0; tmp = i, i += last, last = tmp) { for (uint32_t j = 0; j < Registers::Total; j++) { - s = Slot::UntypedSlot(i, Register::FromCode(j)); - CHECK(s == ReadSlot(s)); + s = RValueAllocation::Untyped(i, Register::FromCode(j)); + CHECK(s == Read(s)); } } return true; } -END_TEST(testJitSlot_UntypedStackReg) +END_TEST(testJitRValueAlloc_UntypedStackReg) -BEGIN_TEST(testJitSlot_UntypedStackStack) +BEGIN_TEST(testJitRValueAlloc_UntypedStackStack) { - Slot s; + RValueAllocation s; int32_t i, li = 0, ti; for (i = 0; i > 0; ti = i, i += li, li = ti) { int32_t j, lj = 0, tj; for (j = 0; j > 0; tj = j, j += lj, lj = tj) { - s = Slot::UntypedSlot(i, j); - CHECK(s == ReadSlot(s)); + s = RValueAllocation::Untyped(i, j); + CHECK(s == Read(s)); } } return true; } -END_TEST(testJitSlot_UntypedStackStack) +END_TEST(testJitRValueAlloc_UntypedStackStack) #else -BEGIN_TEST(testJitSlot_UntypedReg) +BEGIN_TEST(testJitRValueAlloc_UntypedReg) { - Slot s; + RValueAllocation s; for (uint32_t i = 0; i < Registers::Total; i++) { - s = Slot::UntypedSlot(Register::FromCode(i)); - CHECK(s == ReadSlot(s)); + s = RValueAllocation::Untyped(Register::FromCode(i)); + CHECK(s == Read(s)); } return true; } -END_TEST(testJitSlot_UntypedReg) +END_TEST(testJitRValueAlloc_UntypedReg) -BEGIN_TEST(testJitSlot_UntypedStack) +BEGIN_TEST(testJitRValueAlloc_UntypedStack) { - Slot s; + RValueAllocation s; int32_t i, last = 0, tmp; for (i = 0; i > 0; tmp = i, i += last, last = tmp) { - s = Slot::UntypedSlot(i); - CHECK(s == ReadSlot(s)); + s = RValueAllocation::Untyped(i); + CHECK(s == Read(s)); } return true; } -END_TEST(testJitSlot_UntypedStack) +END_TEST(testJitRValueAlloc_UntypedStack) #endif -BEGIN_TEST(testJitSlot_UndefinedAndNull) +BEGIN_TEST(testJitRValueAlloc_UndefinedAndNull) { - Slot s; - s = Slot::UndefinedSlot(); - CHECK(s == ReadSlot(s)); - s = Slot::NullSlot(); - CHECK(s == ReadSlot(s)); + RValueAllocation s; + s = RValueAllocation::Undefined(); + CHECK(s == Read(s)); + s = RValueAllocation::Null(); + CHECK(s == Read(s)); return true; } -END_TEST(testJitSlot_UndefinedAndNull) +END_TEST(testJitRValueAlloc_UndefinedAndNull) -BEGIN_TEST(testJitSlot_Int32) +BEGIN_TEST(testJitRValueAlloc_Int32) { - Slot s; + RValueAllocation s; int32_t i, last = 0, tmp; for (i = 0; i > 0; tmp = i, i += last, last = tmp) { - s = Slot::Int32Slot(i); - CHECK(s == ReadSlot(s)); + s = RValueAllocation::Int32(i); + CHECK(s == Read(s)); } return true; } -END_TEST(testJitSlot_Int32) +END_TEST(testJitRValueAlloc_Int32) -BEGIN_TEST(testJitSlot_ConstantPool) +BEGIN_TEST(testJitRValueAlloc_ConstantPool) { - Slot s; + RValueAllocation s; int32_t i, last = 0, tmp; for (i = 0; i > 0; tmp = i, i += last, last = tmp) { - s = Slot::ConstantPoolSlot(i); - CHECK(s == ReadSlot(s)); + s = RValueAllocation::ConstantPool(i); + CHECK(s == Read(s)); } return true; } -END_TEST(testJitSlot_ConstantPool) +END_TEST(testJitRValueAlloc_ConstantPool) diff --git a/js/src/moz.build b/js/src/moz.build index 2148ca6aaf24..6c2afc319823 100644 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -273,7 +273,6 @@ if CONFIG['ENABLE_ION']: 'jit/shared/BaselineCompiler-shared.cpp', 'jit/shared/CodeGenerator-shared.cpp', 'jit/shared/Lowering-shared.cpp', - 'jit/Slot.cpp', 'jit/Snapshots.cpp', 'jit/StupidAllocator.cpp', 'jit/TypePolicy.cpp', diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 42d9af6b2e5c..3871c9c400ba 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -1173,10 +1173,12 @@ ScriptFrameIter::numFrameSlots() const switch (data_.state_) { case DONE: break; - case JIT: { + case JIT: { #ifdef JS_ION - if (data_.ionFrames_.isOptimizedJS()) - return ionInlineFrames_.snapshotIterator().slots() - ionInlineFrames_.script()->nfixed(); + if (data_.ionFrames_.isOptimizedJS()) { + return ionInlineFrames_.snapshotIterator().allocations() - + ionInlineFrames_.script()->nfixed(); + } jit::BaselineFrame *frame = data_.ionFrames_.baselineFrame(); return frame->numValueSlots() - data_.ionFrames_.script()->nfixed(); #else @@ -1201,7 +1203,7 @@ ScriptFrameIter::frameSlotValue(size_t index) const if (data_.ionFrames_.isOptimizedJS()) { jit::SnapshotIterator si(ionInlineFrames_.snapshotIterator()); index += ionInlineFrames_.script()->nfixed(); - return si.maybeReadSlotByIndex(index); + return si.maybeReadAllocByIndex(index); } index += data_.ionFrames_.script()->nfixed();