2010-10-29 08:05:55 -07:00
|
|
|
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 40; indent-tabs-mode: nil -*- */
|
|
|
|
/* vim: set ts=40 sw=4 et tw=99: */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is the Mozilla SpiderMonkey bytecode type inference
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Mozilla Foundation
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Brian Hackett <bhackett@mozilla.com>
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
|
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
/* Definitions related to javascript type inference. */
|
|
|
|
|
|
|
|
#ifndef jsinfer_h___
|
|
|
|
#define jsinfer_h___
|
|
|
|
|
|
|
|
#include "jsarena.h"
|
|
|
|
#include "jstl.h"
|
|
|
|
#include "jsprvtd.h"
|
2010-12-19 12:21:15 -08:00
|
|
|
#include "jsvalue.h"
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2011-03-03 14:07:48 -08:00
|
|
|
namespace js {
|
|
|
|
struct CallArgs;
|
|
|
|
namespace analyze {
|
2010-10-29 08:05:55 -07:00
|
|
|
struct Bytecode;
|
|
|
|
class Script;
|
|
|
|
} }
|
|
|
|
|
|
|
|
namespace js {
|
|
|
|
namespace types {
|
|
|
|
|
|
|
|
/* Forward declarations. */
|
|
|
|
struct TypeSet;
|
|
|
|
struct TypeCallsite;
|
|
|
|
struct TypeObject;
|
|
|
|
struct TypeFunction;
|
|
|
|
struct TypeCompartment;
|
2011-03-15 23:50:44 -07:00
|
|
|
struct ClonedTypeSet;
|
2010-10-29 08:05:55 -07:00
|
|
|
|
|
|
|
/*
|
2011-04-07 16:12:37 -07:00
|
|
|
* Information about a single concrete type. This is a non-zero value whose
|
2010-10-29 08:05:55 -07:00
|
|
|
* lower 3 bits indicate a particular primitive type below, and if those bits
|
|
|
|
* are zero then a pointer to a type object.
|
|
|
|
*/
|
2011-03-31 03:26:10 -07:00
|
|
|
typedef jsuword jstype;
|
2010-10-29 08:05:55 -07:00
|
|
|
|
|
|
|
/* The primitive types. */
|
|
|
|
const jstype TYPE_UNDEFINED = 1;
|
|
|
|
const jstype TYPE_NULL = 2;
|
|
|
|
const jstype TYPE_BOOLEAN = 3;
|
|
|
|
const jstype TYPE_INT32 = 4;
|
|
|
|
const jstype TYPE_DOUBLE = 5;
|
|
|
|
const jstype TYPE_STRING = 6;
|
|
|
|
|
|
|
|
/*
|
2011-04-07 16:12:37 -07:00
|
|
|
* Aggregate unknown type, could be anything. Typically used when a type set
|
2010-10-29 08:05:55 -07:00
|
|
|
* becomes polymorphic, or when accessing an object with unknown properties.
|
|
|
|
*/
|
|
|
|
const jstype TYPE_UNKNOWN = 7;
|
|
|
|
|
|
|
|
/*
|
2011-04-07 16:12:37 -07:00
|
|
|
* Test whether a type is an primitive or an object. Object types can be
|
2010-10-29 08:05:55 -07:00
|
|
|
* cast into a TypeObject*.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
TypeIsPrimitive(jstype type)
|
|
|
|
{
|
2011-03-11 16:29:38 -08:00
|
|
|
JS_ASSERT(type);
|
2010-10-29 08:05:55 -07:00
|
|
|
return type < TYPE_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
TypeIsObject(jstype type)
|
|
|
|
{
|
2011-03-11 16:29:38 -08:00
|
|
|
JS_ASSERT(type);
|
2010-10-29 08:05:55 -07:00
|
|
|
return type > TYPE_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the type of a jsval, or zero for an unknown special value. */
|
|
|
|
inline jstype GetValueType(JSContext *cx, const Value &val);
|
|
|
|
|
2011-03-01 13:10:05 -08:00
|
|
|
/*
|
|
|
|
* Type inference memory management overview.
|
|
|
|
*
|
|
|
|
* Inference constructs a global web of constraints relating the contents of
|
|
|
|
* type sets particular to various scripts and type objects within a compartment.
|
|
|
|
* There are two issues at hand to manage inference memory: collecting
|
|
|
|
* the constraints, and collecting type sets (on TypeObject destruction).
|
|
|
|
*
|
|
|
|
* The constraints and types generated during analysis of a script depend entirely on
|
|
|
|
* that script's input type sets --- the types of its arguments, upvar locals,
|
|
|
|
* callee return values, object properties, and dynamic types (overflows, undefined
|
|
|
|
* reads, etc.). On a GC, we collect the analysis information for all scripts
|
|
|
|
* which have been analyzed, destroying the type constraints and intermediate
|
|
|
|
* type sets associated with stack values, and add new condensed constraints to
|
|
|
|
* the script's inputs which will trigger reanalysis and recompilation should
|
|
|
|
* that input change in the future.
|
|
|
|
*
|
|
|
|
* TypeObjects are collected when either the script they are associated with is
|
|
|
|
* destroyed or their prototype JSObject is destroyed.
|
|
|
|
*
|
|
|
|
* If a GC happens while we are in the middle of analysis or working with a TypeScript
|
|
|
|
* or TypeObject, we do not destroy/condense analysis information or collect any
|
|
|
|
* TypeObjects or JSScripts. This is controlled with AutoEnterTypeInference.
|
|
|
|
*/
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/*
|
|
|
|
* A constraint which listens to additions to a type set and propagates those
|
|
|
|
* changes to other type sets.
|
|
|
|
*/
|
|
|
|
class TypeConstraint
|
|
|
|
{
|
|
|
|
public:
|
2010-11-18 15:18:23 -08:00
|
|
|
#ifdef DEBUG
|
|
|
|
const char *kind_;
|
|
|
|
const char *kind() const { return kind_; }
|
|
|
|
#else
|
|
|
|
const char *kind() const { return NULL; }
|
2010-10-29 08:05:55 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Next constraint listening to the same type set. */
|
|
|
|
TypeConstraint *next;
|
|
|
|
|
2011-03-01 13:10:05 -08:00
|
|
|
/*
|
|
|
|
* Script this constraint indicates an input for. If this constraint
|
|
|
|
* is not on an intermediate (script-local) type set, then during
|
|
|
|
* GC this will be replaced with a condensed input type constraint.
|
|
|
|
*/
|
|
|
|
JSScript *script;
|
|
|
|
|
|
|
|
TypeConstraint(const char *kind, JSScript *script)
|
|
|
|
: next(NULL), script(script)
|
2010-10-29 08:05:55 -07:00
|
|
|
{
|
2011-03-01 13:10:05 -08:00
|
|
|
JS_ASSERT(script);
|
2010-11-18 15:18:23 -08:00
|
|
|
#ifdef DEBUG
|
|
|
|
this->kind_ = kind;
|
2010-10-29 08:05:55 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Register a new type for the set this constraint is listening to. */
|
|
|
|
virtual void newType(JSContext *cx, TypeSet *source, jstype type) = 0;
|
2010-11-05 07:37:09 -07:00
|
|
|
|
2011-04-11 20:10:46 -07:00
|
|
|
/*
|
|
|
|
* For constraints attached to an object property's type set, mark the
|
|
|
|
* property as having been configured or received an own property.
|
|
|
|
*/
|
|
|
|
virtual void newPropertyState(JSContext *cx, TypeSet *source) {}
|
|
|
|
|
2010-11-05 07:37:09 -07:00
|
|
|
/*
|
2011-03-19 16:53:07 -07:00
|
|
|
* For constraints attached to the index type set of an object (JSID_VOID),
|
2011-04-05 18:12:03 -07:00
|
|
|
* mark a change in one of the object's dynamic property flags.
|
2010-11-05 07:37:09 -07:00
|
|
|
*/
|
2011-04-11 20:10:46 -07:00
|
|
|
virtual void newObjectState(JSContext *cx, TypeObject *object) {}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For constraints attached to the index type set of a global object,
|
|
|
|
* mark a reallocation on the object's dynamic slots. This can happen
|
|
|
|
* multiple times over the life of the object.
|
|
|
|
*/
|
|
|
|
virtual void slotsReallocation(JSContext *cx) {}
|
2011-03-01 13:10:05 -08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Whether this is an input type constraint condensed from the original
|
|
|
|
* constraints generated during analysis of the associated script.
|
|
|
|
* If this type set changes then the script will be reanalyzed/recompiled
|
|
|
|
* should the type set change at all in the future.
|
|
|
|
*/
|
|
|
|
virtual bool condensed() { return false; }
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this is a persistent subset constraint, the object being propagated
|
|
|
|
* into. Such constraints describe relationships between TypeObject
|
|
|
|
* properties which are independent of the analysis of any script.
|
|
|
|
*/
|
|
|
|
virtual TypeObject * baseSubset() { return NULL; }
|
2010-11-05 07:37:09 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2011-04-07 16:12:37 -07:00
|
|
|
* Coarse kinds of a set of objects. These form the following lattice:
|
2010-11-05 07:37:09 -07:00
|
|
|
*
|
2011-04-05 18:12:03 -07:00
|
|
|
* NONE
|
|
|
|
* ____/ \_____
|
|
|
|
* / \
|
|
|
|
* PACKED_ARRAY INLINEABLE_FUNCTION
|
|
|
|
* | |
|
|
|
|
* DENSE_ARRAY SCRIPTED_FUNCTION
|
|
|
|
* \____ _____/
|
|
|
|
* \ /
|
|
|
|
* NO_SPECIAL_EQUALITY
|
|
|
|
* |
|
|
|
|
* UNKNOWN
|
2010-11-05 07:37:09 -07:00
|
|
|
*/
|
|
|
|
enum ObjectKind {
|
|
|
|
OBJECT_NONE,
|
|
|
|
OBJECT_UNKNOWN,
|
|
|
|
OBJECT_PACKED_ARRAY,
|
2011-04-05 18:12:03 -07:00
|
|
|
OBJECT_DENSE_ARRAY, /* Excludes arrays whose length has shrunk. */
|
2011-03-26 19:07:13 -07:00
|
|
|
OBJECT_INLINEABLE_FUNCTION,
|
2010-11-05 07:37:09 -07:00
|
|
|
OBJECT_SCRIPTED_FUNCTION,
|
2011-03-19 16:53:07 -07:00
|
|
|
OBJECT_NO_SPECIAL_EQUALITY
|
2010-10-29 08:05:55 -07:00
|
|
|
};
|
|
|
|
|
2011-03-03 14:07:48 -08:00
|
|
|
/* Coarse flags for the contents of a type set. */
|
|
|
|
enum {
|
|
|
|
TYPE_FLAG_UNDEFINED = 1 << TYPE_UNDEFINED,
|
|
|
|
TYPE_FLAG_NULL = 1 << TYPE_NULL,
|
|
|
|
TYPE_FLAG_BOOLEAN = 1 << TYPE_BOOLEAN,
|
|
|
|
TYPE_FLAG_INT32 = 1 << TYPE_INT32,
|
|
|
|
TYPE_FLAG_DOUBLE = 1 << TYPE_DOUBLE,
|
|
|
|
TYPE_FLAG_STRING = 1 << TYPE_STRING,
|
|
|
|
|
|
|
|
TYPE_FLAG_UNKNOWN = 1 << TYPE_UNKNOWN,
|
|
|
|
|
|
|
|
/* Flag for type sets which are cleared on GC. */
|
2011-04-11 20:10:46 -07:00
|
|
|
TYPE_FLAG_INTERMEDIATE_SET = 0x1000,
|
|
|
|
|
|
|
|
/* For object property type sets, whether this property has been directly written. */
|
|
|
|
TYPE_FLAG_OWN_PROPERTY = 0x2000,
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For object property type sets, whether the property has ever been
|
|
|
|
* deleted or reconfigured as non-writable.
|
|
|
|
*/
|
|
|
|
TYPE_FLAG_CONFIGURED_PROPERTY = 0x4000,
|
|
|
|
|
|
|
|
/* Mask of non-type flags on a type set. */
|
|
|
|
TYPE_FLAG_BASE_MASK = 0x7000
|
2011-03-03 14:07:48 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Vector of the above flags. */
|
|
|
|
typedef uint32 TypeFlags;
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/* Information about the set of types associated with an lvalue. */
|
2011-04-05 18:12:03 -07:00
|
|
|
class TypeSet
|
2010-10-29 08:05:55 -07:00
|
|
|
{
|
|
|
|
/* Flags for the possible coarse types in this set. */
|
|
|
|
TypeFlags typeFlags;
|
|
|
|
|
2011-03-03 14:07:48 -08:00
|
|
|
/* Possible objects this type set can represent. */
|
2010-10-29 08:05:55 -07:00
|
|
|
TypeObject **objectSet;
|
|
|
|
unsigned objectCount;
|
|
|
|
|
2011-04-05 18:12:03 -07:00
|
|
|
public:
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/* Chain of constraints which propagate changes out from this type set. */
|
|
|
|
TypeConstraint *constraintList;
|
|
|
|
|
2011-03-01 13:10:05 -08:00
|
|
|
TypeSet()
|
2010-10-29 08:05:55 -07:00
|
|
|
: typeFlags(0), objectSet(NULL), objectCount(0), constraintList(NULL)
|
2011-03-01 13:10:05 -08:00
|
|
|
{}
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2010-11-18 15:18:23 -08:00
|
|
|
void print(JSContext *cx);
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2011-03-03 14:07:48 -08:00
|
|
|
void setIntermediate() { typeFlags |= TYPE_FLAG_INTERMEDIATE_SET; }
|
2011-04-11 20:10:46 -07:00
|
|
|
void setOwnProperty(bool configurable) {
|
|
|
|
typeFlags |= TYPE_FLAG_OWN_PROPERTY;
|
|
|
|
if (configurable)
|
|
|
|
typeFlags |= TYPE_FLAG_CONFIGURED_PROPERTY;
|
|
|
|
}
|
2011-03-03 14:07:48 -08:00
|
|
|
|
|
|
|
inline void destroy(JSContext *cx);
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/* Whether this set contains a specific type. */
|
|
|
|
inline bool hasType(jstype type);
|
|
|
|
|
2011-04-11 20:10:46 -07:00
|
|
|
TypeFlags baseFlags() { return typeFlags & ~TYPE_FLAG_BASE_MASK; }
|
2011-04-05 18:12:03 -07:00
|
|
|
bool hasAnyFlag(TypeFlags flags) { return typeFlags & flags; }
|
2010-12-21 07:32:21 -08:00
|
|
|
bool unknown() { return typeFlags & TYPE_FLAG_UNKNOWN; }
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/*
|
|
|
|
* Add a type to this set, calling any constraint handlers if this is a new
|
|
|
|
* possible type.
|
|
|
|
*/
|
|
|
|
inline void addType(JSContext *cx, jstype type);
|
|
|
|
|
2011-03-15 23:50:44 -07:00
|
|
|
/* Add all types in a cloned set to this set. */
|
|
|
|
void addTypeSet(JSContext *cx, ClonedTypeSet *types);
|
|
|
|
|
2011-04-11 20:10:46 -07:00
|
|
|
/* Mark this type set as representing an own property or configured property. */
|
|
|
|
inline void setOwnProperty(JSContext *cx, bool configured);
|
|
|
|
|
2011-04-05 18:12:03 -07:00
|
|
|
/*
|
|
|
|
* Iterate through the objects in this set. getObjectCount overapproximates
|
|
|
|
* in the hash case (see SET_ARRAY_SIZE in jsinferinlines.h), and getObject
|
|
|
|
* may return NULL.
|
|
|
|
*/
|
|
|
|
inline unsigned getObjectCount();
|
|
|
|
inline TypeObject *getObject(unsigned i);
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/* Add specific kinds of constraints to this set. */
|
2010-11-05 07:37:09 -07:00
|
|
|
inline void add(JSContext *cx, TypeConstraint *constraint, bool callExisting = true);
|
2011-03-01 13:10:05 -08:00
|
|
|
void addSubset(JSContext *cx, JSScript *script, TypeSet *target);
|
2010-12-28 11:53:50 -08:00
|
|
|
void addGetProperty(JSContext *cx, JSScript *script, const jsbytecode *pc,
|
|
|
|
TypeSet *target, jsid id);
|
|
|
|
void addSetProperty(JSContext *cx, JSScript *script, const jsbytecode *pc,
|
|
|
|
TypeSet *target, jsid id);
|
2011-03-01 13:10:05 -08:00
|
|
|
void addNewObject(JSContext *cx, JSScript *script, TypeFunction *fun, TypeSet *target);
|
2010-10-29 08:05:55 -07:00
|
|
|
void addCall(JSContext *cx, TypeCallsite *site);
|
2011-03-01 13:10:05 -08:00
|
|
|
void addArith(JSContext *cx, JSScript *script,
|
2010-10-29 08:05:55 -07:00
|
|
|
TypeSet *target, TypeSet *other = NULL);
|
2010-12-28 11:53:50 -08:00
|
|
|
void addTransformThis(JSContext *cx, JSScript *script, TypeSet *target);
|
2011-03-01 13:10:05 -08:00
|
|
|
void addFilterPrimitives(JSContext *cx, JSScript *script,
|
2010-12-28 11:53:50 -08:00
|
|
|
TypeSet *target, bool onlyNullVoid);
|
2011-03-01 13:10:05 -08:00
|
|
|
void addMonitorRead(JSContext *cx, JSScript *script, TypeSet *target);
|
|
|
|
|
|
|
|
void addBaseSubset(JSContext *cx, TypeObject *object, TypeSet *target);
|
|
|
|
void addCondensed(JSContext *cx, JSScript *script);
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2010-11-05 07:37:09 -07:00
|
|
|
/*
|
|
|
|
* Make an intermediate type set with the specified debugging name,
|
|
|
|
* not embedded in another structure.
|
|
|
|
*/
|
2011-03-03 14:07:48 -08:00
|
|
|
static inline TypeSet* make(JSContext *cx, const char *name);
|
2010-11-05 07:37:09 -07:00
|
|
|
|
2010-11-03 15:07:49 -07:00
|
|
|
/*
|
2011-03-30 14:10:16 -07:00
|
|
|
* Methods for JIT compilation. If a script is currently being compiled
|
|
|
|
* (see AutoEnterCompilation) these will add constraints ensuring that if
|
|
|
|
* the return value change in the future due to new type information, the
|
|
|
|
* currently compiled script will be marked for recompilation.
|
2010-11-03 15:07:49 -07:00
|
|
|
*/
|
2011-03-11 16:29:38 -08:00
|
|
|
|
2011-03-27 18:25:05 -07:00
|
|
|
/* Completely freeze the contents of this type set. */
|
2011-03-30 14:10:16 -07:00
|
|
|
void addFreeze(JSContext *cx);
|
2011-03-27 18:25:05 -07:00
|
|
|
|
2011-03-11 16:29:38 -08:00
|
|
|
/* Get any type tag which all values in this set must have. */
|
2011-03-30 14:10:16 -07:00
|
|
|
JSValueType getKnownTypeTag(JSContext *cx);
|
2010-11-01 20:03:46 -07:00
|
|
|
|
2010-11-05 07:37:09 -07:00
|
|
|
/* Get information about the kinds of objects in this type set. */
|
2011-03-30 14:10:16 -07:00
|
|
|
ObjectKind getKnownObjectKind(JSContext *cx);
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2011-04-05 18:12:03 -07:00
|
|
|
/* Get the fixed kind of a particular object. */
|
|
|
|
static ObjectKind GetObjectKind(JSContext *cx, TypeObject *object);
|
|
|
|
|
2011-04-11 20:10:46 -07:00
|
|
|
/* Watch for slot reallocations on a particular object. */
|
|
|
|
static void WatchObjectReallocation(JSContext *cx, JSObject *object);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For type sets on a property, return true if the property has any 'own'
|
|
|
|
* values assigned. If configurable is set, return 'true' if the property
|
|
|
|
* has additionally been reconfigured as non-configurable, non-enumerable
|
|
|
|
* or non-writable (this only applies to properties that have changed after
|
|
|
|
* having been created, not to e.g. properties non-writable on creation).
|
|
|
|
*/
|
|
|
|
bool isOwnProperty(JSContext *cx, bool configurable);
|
|
|
|
|
2011-03-19 16:53:07 -07:00
|
|
|
/* Whether any objects in this type set have unknown properties. */
|
2011-03-30 14:10:16 -07:00
|
|
|
bool hasUnknownProperties(JSContext *cx);
|
2011-03-19 16:53:07 -07:00
|
|
|
|
2010-12-15 18:21:45 -08:00
|
|
|
/* Get whether this type set is non-empty. */
|
2011-03-30 14:10:16 -07:00
|
|
|
bool knownNonEmpty(JSContext *cx);
|
2011-03-09 11:04:36 -08:00
|
|
|
|
2011-03-21 22:55:27 -07:00
|
|
|
/* Get the single value which can appear in this type set, otherwise NULL. */
|
2011-03-30 14:10:16 -07:00
|
|
|
JSObject *getSingleton(JSContext *cx);
|
2011-03-21 22:55:27 -07:00
|
|
|
|
2011-03-19 08:20:46 -07:00
|
|
|
/* Mark all current and future types in this set as pushed by script/pc. */
|
|
|
|
void pushAllTypes(JSContext *cx, JSScript *script, const jsbytecode *pc);
|
|
|
|
|
2011-03-15 23:50:44 -07:00
|
|
|
/*
|
2011-03-19 08:20:46 -07:00
|
|
|
* Clone (possibly NULL) source onto target; if any new types are added to
|
|
|
|
* source in the future, the script will be recompiled.
|
2011-03-15 23:50:44 -07:00
|
|
|
*/
|
2011-03-30 14:10:16 -07:00
|
|
|
static void Clone(JSContext *cx, TypeSet *source, ClonedTypeSet *target);
|
2011-03-15 23:50:44 -07:00
|
|
|
|
2011-04-05 18:12:03 -07:00
|
|
|
static void
|
|
|
|
CondenseSweepTypeSet(JSContext *cx, TypeCompartment *compartment,
|
|
|
|
HashSet<JSScript*> *pcondensed, TypeSet *types);
|
|
|
|
|
2011-03-09 11:04:36 -08:00
|
|
|
private:
|
|
|
|
inline void markUnknown(JSContext *cx);
|
2010-10-29 08:05:55 -07:00
|
|
|
};
|
|
|
|
|
2011-03-15 23:50:44 -07:00
|
|
|
/* A type set captured for use by JIT compilers. */
|
|
|
|
struct ClonedTypeSet
|
|
|
|
{
|
|
|
|
TypeFlags typeFlags;
|
|
|
|
TypeObject **objectSet;
|
|
|
|
unsigned objectCount;
|
|
|
|
};
|
|
|
|
|
2010-11-24 17:41:52 -08:00
|
|
|
/* Type information about a property. */
|
|
|
|
struct Property
|
2010-10-29 08:05:55 -07:00
|
|
|
{
|
2010-11-24 17:41:52 -08:00
|
|
|
/* Identifier for this property, JSID_VOID for the aggregate integer index property. */
|
|
|
|
jsid id;
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2010-11-24 17:41:52 -08:00
|
|
|
/* Possible types for this property, including types inherited from prototypes. */
|
|
|
|
TypeSet types;
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2011-03-01 13:10:05 -08:00
|
|
|
Property(jsid id)
|
|
|
|
: id(id)
|
2010-11-24 17:41:52 -08:00
|
|
|
{}
|
2010-11-20 15:45:52 -08:00
|
|
|
|
2010-11-24 17:41:52 -08:00
|
|
|
static uint32 keyBits(jsid id) { return (uint32) JSID_BITS(id); }
|
|
|
|
static jsid getKey(Property *p) { return p->id; }
|
2010-10-29 08:05:55 -07:00
|
|
|
};
|
|
|
|
|
2011-04-05 18:12:03 -07:00
|
|
|
/* Bitmask for possible dynamic properties of the JSObjects with some type. */
|
|
|
|
enum {
|
|
|
|
/*
|
|
|
|
* Whether all the properties of this object are unknown. When this object
|
|
|
|
* appears in a type set, nothing can be assumed about its contents,
|
|
|
|
* including whether the .proto field is correct. This is needed to handle
|
|
|
|
* mutable __proto__, which requires us to unify all type objects with
|
|
|
|
* unknown properties in type sets (see SetProto).
|
|
|
|
*/
|
|
|
|
OBJECT_FLAG_UNKNOWN_MASK = uint32(-1),
|
|
|
|
|
|
|
|
/* Whether any objects this represents are not dense arrays. */
|
|
|
|
OBJECT_FLAG_NON_DENSE_ARRAY = 1 << 0,
|
|
|
|
|
|
|
|
/* Whether any objects this represents are not packed arrays. */
|
|
|
|
OBJECT_FLAG_NON_PACKED_ARRAY = 1 << 1,
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Whether any objects this represents are arrays whose length has shrunk
|
|
|
|
* due to explicit assignments to .length.
|
|
|
|
*/
|
|
|
|
OBJECT_FLAG_ARRAY_SHRANK = 1 << 2,
|
|
|
|
|
|
|
|
/* Whether any objects this represents have had their .arguments accessed. */
|
|
|
|
OBJECT_FLAG_UNINLINEABLE = 1 << 3,
|
|
|
|
|
|
|
|
/* Whether any objects this represents have an equality hook. */
|
|
|
|
OBJECT_FLAG_SPECIAL_EQUALITY = 1 << 4
|
|
|
|
};
|
|
|
|
typedef uint32 TypeObjectFlags;
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/* Type information about an object accessed by a script. */
|
|
|
|
struct TypeObject
|
|
|
|
{
|
2010-12-18 20:44:51 -08:00
|
|
|
#ifdef DEBUG
|
|
|
|
/* Name of this object. */
|
|
|
|
jsid name_;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Prototype shared by objects using this type. */
|
|
|
|
JSObject *proto;
|
|
|
|
|
|
|
|
/* Lazily filled array of empty shapes for each size of objects with this type. */
|
|
|
|
js::EmptyShape **emptyShapes;
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2011-04-05 18:12:03 -07:00
|
|
|
/* Vector of TypeObjectFlags for the objects this type represents. */
|
|
|
|
TypeObjectFlags flags;
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/* Whether this is a function object, and may be cast into TypeFunction. */
|
|
|
|
bool isFunction;
|
|
|
|
|
2010-12-18 20:44:51 -08:00
|
|
|
/* Mark bit for GC. */
|
|
|
|
bool marked;
|
|
|
|
|
2010-12-28 11:53:50 -08:00
|
|
|
/*
|
|
|
|
* Whether this is an Object or Array keyed to an offset in the script containing
|
|
|
|
* this in its objects list.
|
|
|
|
*/
|
|
|
|
bool initializerObject;
|
|
|
|
bool initializerArray;
|
|
|
|
uint32 initializerOffset;
|
|
|
|
|
2011-03-09 11:04:36 -08:00
|
|
|
/*
|
|
|
|
* Estimate of the contribution of this object to the type sets it appears in.
|
|
|
|
* This is the sum of the sizes of those sets at the point when the object
|
|
|
|
* was added.
|
|
|
|
*
|
|
|
|
* When the contribution exceeds the CONTRIBUTION_LIMIT, any type sets the
|
|
|
|
* object is added to are instead marked as unknown. If we get to this point
|
|
|
|
* we are probably not adding types which will let us do meaningful optimization
|
|
|
|
* later, and we want to ensure in such cases that our time/space complexity
|
|
|
|
* is linear, not worst-case cubic as it would otherwise be.
|
|
|
|
*/
|
|
|
|
uint32 contribution;
|
|
|
|
static const uint32 CONTRIBUTION_LIMIT = 20000;
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/*
|
2010-12-18 20:44:51 -08:00
|
|
|
* Properties of this object. This may contain JSID_VOID, representing the types
|
|
|
|
* of all integer indexes of the object, and/or JSID_EMPTY, representing the types
|
|
|
|
* of new objects that can be created with different instances of this type.
|
2010-10-29 08:05:55 -07:00
|
|
|
*/
|
2010-11-24 17:41:52 -08:00
|
|
|
Property **propertySet;
|
|
|
|
unsigned propertyCount;
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2010-11-24 17:41:52 -08:00
|
|
|
/* List of objects using this one as their prototype. */
|
|
|
|
TypeObject *instanceList;
|
|
|
|
|
|
|
|
/* Chain for objects sharing the same prototype. */
|
|
|
|
TypeObject *instanceNext;
|
|
|
|
|
2011-03-09 09:58:49 -08:00
|
|
|
/* Link in the list of objects associated with a script or global object. */
|
2010-11-24 17:41:52 -08:00
|
|
|
TypeObject *next;
|
|
|
|
|
2011-03-26 19:07:13 -07:00
|
|
|
/* If at most one JSObject can have this as its type, that object. */
|
2011-03-21 22:55:27 -07:00
|
|
|
JSObject *singleton;
|
|
|
|
|
2010-12-18 20:44:51 -08:00
|
|
|
TypeObject() {}
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/* Make an object with the specified name. */
|
2011-03-01 13:10:05 -08:00
|
|
|
inline TypeObject(jsid id, JSObject *proto);
|
2010-10-29 08:05:55 -07:00
|
|
|
|
|
|
|
/* Coerce this object to a function. */
|
|
|
|
TypeFunction* asFunction()
|
|
|
|
{
|
2010-11-05 07:37:09 -07:00
|
|
|
JS_ASSERT(isFunction);
|
|
|
|
return (TypeFunction *) this;
|
2010-10-29 08:05:55 -07:00
|
|
|
}
|
|
|
|
|
2011-04-05 18:12:03 -07:00
|
|
|
bool unknownProperties() { return flags == OBJECT_FLAG_UNKNOWN_MASK; }
|
|
|
|
bool hasFlags(TypeObjectFlags flags) { return (this->flags & flags) == flags; }
|
|
|
|
|
2010-12-18 20:44:51 -08:00
|
|
|
/*
|
|
|
|
* Return an immutable, shareable, empty shape with the same clasp as this
|
|
|
|
* and the same slotSpan as this had when empty.
|
|
|
|
*
|
|
|
|
* If |this| is the scope of an object |proto|, the resulting scope can be
|
|
|
|
* used as the scope of a new object whose prototype is |proto|.
|
|
|
|
*/
|
|
|
|
inline bool canProvideEmptyShape(js::Class *clasp);
|
|
|
|
inline js::EmptyShape *getEmptyShape(JSContext *cx, js::Class *aclasp,
|
|
|
|
/* gc::FinalizeKind */ unsigned kind);
|
|
|
|
|
2010-11-24 17:41:52 -08:00
|
|
|
/*
|
|
|
|
* Get or create a property of this object. Only call this for properties which
|
|
|
|
* a script accesses explicitly. 'assign' indicates whether this is for an
|
|
|
|
* assignment, and the own types of the property will be used instead of
|
|
|
|
* aggregate types.
|
|
|
|
*/
|
|
|
|
inline TypeSet *getProperty(JSContext *cx, jsid id, bool assign);
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2010-12-18 20:44:51 -08:00
|
|
|
inline const char * name();
|
|
|
|
|
|
|
|
/* Mark proto as the prototype of this object and all instances. */
|
2010-12-23 14:54:03 -08:00
|
|
|
void splicePrototype(JSContext *cx, JSObject *proto);
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2011-04-05 18:12:03 -07:00
|
|
|
inline unsigned getPropertyCount();
|
|
|
|
inline Property *getProperty(unsigned i);
|
|
|
|
|
2010-11-24 17:41:52 -08:00
|
|
|
/* Helpers */
|
2010-11-20 15:45:52 -08:00
|
|
|
|
2011-03-03 14:07:48 -08:00
|
|
|
bool addProperty(JSContext *cx, jsid id, Property **pprop);
|
2010-11-24 17:41:52 -08:00
|
|
|
void addPrototype(JSContext *cx, TypeObject *proto);
|
2011-04-05 18:12:03 -07:00
|
|
|
void setFlags(JSContext *cx, TypeObjectFlags flags);
|
2010-11-24 17:41:52 -08:00
|
|
|
void markUnknown(JSContext *cx);
|
|
|
|
void storeToInstances(JSContext *cx, Property *base);
|
2010-12-23 14:54:03 -08:00
|
|
|
void getFromPrototypes(JSContext *cx, Property *base);
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2010-11-18 15:18:23 -08:00
|
|
|
void print(JSContext *cx);
|
2010-12-18 20:44:51 -08:00
|
|
|
void trace(JSTracer *trc);
|
2010-10-29 08:05:55 -07:00
|
|
|
};
|
|
|
|
|
2010-12-20 09:06:43 -08:00
|
|
|
/*
|
|
|
|
* Type information about an interpreted or native function. Note: it is possible for
|
|
|
|
* a function JSObject to have a type which is not a TypeFunction. This happens when
|
|
|
|
* we are not able to statically model the type of a function due to non-compileAndGo code.
|
|
|
|
*/
|
2010-10-29 08:05:55 -07:00
|
|
|
struct TypeFunction : public TypeObject
|
|
|
|
{
|
|
|
|
/* If this function is native, the handler to use at calls to it. */
|
|
|
|
JSTypeHandler handler;
|
|
|
|
|
|
|
|
/* If this function is interpreted, the corresponding script. */
|
|
|
|
JSScript *script;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Whether this is a generic native handler, and treats its first parameter
|
|
|
|
* the way it normally would its 'this' variable, e.g. Array.reverse(arr)
|
|
|
|
* instead of arr.reverse().
|
|
|
|
*/
|
|
|
|
bool isGeneric;
|
|
|
|
|
2011-03-01 13:10:05 -08:00
|
|
|
inline TypeFunction(jsid id, JSObject *proto);
|
2010-10-29 08:05:55 -07:00
|
|
|
};
|
|
|
|
|
2010-12-28 11:53:50 -08:00
|
|
|
/*
|
|
|
|
* Type information about a callsite. this is separated from the bytecode
|
|
|
|
* information itself so we can handle higher order functions not called
|
|
|
|
* directly via a bytecode.
|
|
|
|
*/
|
|
|
|
struct TypeCallsite
|
|
|
|
{
|
|
|
|
JSScript *script;
|
|
|
|
const jsbytecode *pc;
|
|
|
|
|
|
|
|
/* Whether this is a 'NEW' call. */
|
|
|
|
bool isNew;
|
|
|
|
|
|
|
|
/* Types of each argument to the call. */
|
|
|
|
TypeSet **argumentTypes;
|
|
|
|
unsigned argumentCount;
|
|
|
|
|
|
|
|
/* Types of the this variable. */
|
|
|
|
TypeSet *thisTypes;
|
|
|
|
|
|
|
|
/* Any definite type for 'this'. */
|
|
|
|
jstype thisType;
|
|
|
|
|
|
|
|
/* Type set receiving the return value of this call. */
|
|
|
|
TypeSet *returnTypes;
|
|
|
|
|
2011-03-03 14:07:48 -08:00
|
|
|
inline TypeCallsite(JSContext *cx, JSScript *script, const jsbytecode *pc,
|
2010-12-28 11:53:50 -08:00
|
|
|
bool isNew, unsigned argumentCount);
|
|
|
|
|
2011-03-03 14:07:48 -08:00
|
|
|
/* Force creation of thisTypes. */
|
|
|
|
inline bool forceThisTypes(JSContext *cx);
|
2010-12-28 11:53:50 -08:00
|
|
|
|
|
|
|
/* Get the new object at this callsite. */
|
|
|
|
inline TypeObject* getInitObject(JSContext *cx, bool isArray);
|
|
|
|
|
|
|
|
inline bool compileAndGo();
|
|
|
|
};
|
|
|
|
|
2011-03-01 13:10:05 -08:00
|
|
|
/*
|
|
|
|
* Type information about a dynamic value pushed by a script's opcode.
|
|
|
|
* These are associated with each JSScript and persist after the
|
|
|
|
* TypeScript is destroyed by GCs.
|
|
|
|
*/
|
|
|
|
struct TypeResult
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Offset pushing the value. TypeResults are only generated for
|
|
|
|
* the first stack slot actually pushed by a bytecode.
|
|
|
|
*/
|
|
|
|
uint32 offset;
|
|
|
|
|
|
|
|
/* Type which was pushed. */
|
|
|
|
jstype type;
|
|
|
|
|
|
|
|
/* Next dynamic result for the script. */
|
|
|
|
TypeResult *next;
|
|
|
|
};
|
|
|
|
|
2010-12-28 11:53:50 -08:00
|
|
|
/* Type information for a script, result of AnalyzeTypes. */
|
|
|
|
struct TypeScript
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
JSScript *script;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Stack values pushed by all bytecodes in the script. Low bit is set for
|
|
|
|
* bytecodes which are monitored (side effects were not determined statically).
|
|
|
|
*/
|
|
|
|
TypeSet **pushedArray;
|
|
|
|
|
|
|
|
/* Gather statistics off this script and print it if necessary. */
|
2011-03-10 16:17:39 -08:00
|
|
|
void print(JSContext *cx, JSScript *script);
|
2010-12-28 11:53:50 -08:00
|
|
|
|
|
|
|
inline bool monitored(uint32 offset);
|
|
|
|
inline void setMonitored(uint32 offset);
|
|
|
|
|
|
|
|
inline TypeSet *pushed(uint32 offset);
|
|
|
|
inline TypeSet *pushed(uint32 offset, uint32 index);
|
|
|
|
|
|
|
|
inline void addType(JSContext *cx, uint32 offset, uint32 index, jstype type);
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Analyzes all types in script, constructing its TypeScript. */
|
2011-03-01 13:10:05 -08:00
|
|
|
void AnalyzeScriptTypes(JSContext *cx, JSScript *script);
|
|
|
|
|
2011-03-10 12:01:11 -08:00
|
|
|
/* Analyze the effect of invoking 'new' on script. */
|
|
|
|
void AnalyzeScriptNew(JSContext *cx, JSScript *script);
|
2010-12-28 11:53:50 -08:00
|
|
|
|
2011-03-10 16:17:39 -08:00
|
|
|
struct ArrayTableKey;
|
2011-03-10 19:25:49 -08:00
|
|
|
typedef HashMap<ArrayTableKey,TypeObject*,ArrayTableKey,SystemAllocPolicy> ArrayTypeTable;
|
2011-03-10 16:17:39 -08:00
|
|
|
|
|
|
|
struct ObjectTableKey;
|
|
|
|
struct ObjectTableEntry;
|
2011-03-10 19:25:49 -08:00
|
|
|
typedef HashMap<ObjectTableKey,ObjectTableEntry,ObjectTableKey,SystemAllocPolicy> ObjectTypeTable;
|
2011-03-10 16:17:39 -08:00
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/* Type information for a compartment. */
|
|
|
|
struct TypeCompartment
|
|
|
|
{
|
2011-03-01 13:10:05 -08:00
|
|
|
/* List of objects not associated with a script. */
|
2010-10-29 08:05:55 -07:00
|
|
|
TypeObject *objects;
|
|
|
|
|
2011-03-03 14:07:48 -08:00
|
|
|
/* Whether type inference is enabled in this compartment. */
|
|
|
|
bool inferenceEnabled;
|
|
|
|
|
|
|
|
/* Whether type inference is active, see AutoEnterTypeInference. */
|
2011-03-01 13:10:05 -08:00
|
|
|
unsigned inferenceDepth;
|
2011-03-03 14:07:48 -08:00
|
|
|
|
|
|
|
/* Pool for all intermediate type information in this compartment. Cleared on every GC. */
|
|
|
|
JSArenaPool pool;
|
2011-03-01 13:10:05 -08:00
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/* Number of scripts in this compartment. */
|
|
|
|
unsigned scriptCount;
|
|
|
|
|
2010-12-18 20:44:51 -08:00
|
|
|
/* Object to use throughout the compartment as the default type of objects with no prototype. */
|
2011-03-09 09:58:49 -08:00
|
|
|
TypeObject typeEmpty;
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2011-03-03 14:07:48 -08:00
|
|
|
/*
|
|
|
|
* Bit set if all current types must be marked as unknown, and all scripts
|
|
|
|
* recompiled. Caused by OOM failure within inference operations.
|
|
|
|
*/
|
|
|
|
bool pendingNukeTypes;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Whether type sets have been nuked, and all future type sets should be as well.
|
|
|
|
* This is not strictly necessary to do, but avoids thrashing from repeated
|
|
|
|
* redundant type nuking.
|
|
|
|
*/
|
|
|
|
bool typesNuked;
|
|
|
|
|
2010-11-18 08:28:05 -08:00
|
|
|
/* Pending recompilations to perform before execution of JIT code can resume. */
|
|
|
|
Vector<JSScript*> *pendingRecompiles;
|
|
|
|
|
2011-03-29 18:51:15 -07:00
|
|
|
/*
|
|
|
|
* Number of recompilation events and inline frame expansions that have
|
|
|
|
* occurred in this compartment. If these change, code should not count on
|
|
|
|
* compiled code or the current stack being intact.
|
|
|
|
*/
|
|
|
|
unsigned recompilations;
|
|
|
|
unsigned frameExpansions;
|
|
|
|
|
2011-03-30 14:10:16 -07:00
|
|
|
/*
|
|
|
|
* Script currently being compiled. All constraints which look for type
|
|
|
|
* changes inducing recompilation are keyed to this script. Note: script
|
|
|
|
* compilation is not reentrant.
|
|
|
|
*/
|
|
|
|
JSScript *compiledScript;
|
|
|
|
|
2011-03-10 16:17:39 -08:00
|
|
|
/* Tables for determining types of singleton/JSON objects. */
|
|
|
|
|
|
|
|
ArrayTypeTable *arrayTypeTable;
|
|
|
|
ObjectTypeTable *objectTypeTable;
|
|
|
|
|
|
|
|
bool fixArrayType(JSContext *cx, JSObject *obj);
|
|
|
|
bool fixObjectType(JSContext *cx, JSObject *obj);
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/* Constraint solving worklist structures. */
|
|
|
|
|
2011-04-07 16:12:37 -07:00
|
|
|
/*
|
|
|
|
* Worklist of types which need to be propagated to constraints. We use a
|
|
|
|
* worklist to avoid blowing the native stack.
|
|
|
|
*/
|
2010-10-29 08:05:55 -07:00
|
|
|
struct PendingWork
|
|
|
|
{
|
|
|
|
TypeConstraint *constraint;
|
|
|
|
TypeSet *source;
|
|
|
|
jstype type;
|
|
|
|
};
|
|
|
|
PendingWork *pendingArray;
|
|
|
|
unsigned pendingCount;
|
|
|
|
unsigned pendingCapacity;
|
|
|
|
|
|
|
|
/* Whether we are currently resolving the pending worklist. */
|
|
|
|
bool resolving;
|
|
|
|
|
|
|
|
/* Logging fields */
|
|
|
|
|
|
|
|
/* Counts of stack type sets with some number of possible operand types. */
|
|
|
|
static const unsigned TYPE_COUNT_LIMIT = 4;
|
|
|
|
unsigned typeCounts[TYPE_COUNT_LIMIT];
|
|
|
|
unsigned typeCountOver;
|
|
|
|
|
2011-03-03 14:07:48 -08:00
|
|
|
void init(JSContext *cx);
|
2011-03-10 16:17:39 -08:00
|
|
|
~TypeCompartment();
|
2010-10-29 08:05:55 -07:00
|
|
|
|
|
|
|
/* Add a type to register with a list of constraints. */
|
|
|
|
inline void addPending(JSContext *cx, TypeConstraint *constraint, TypeSet *source, jstype type);
|
2011-03-01 13:10:05 -08:00
|
|
|
void growPendingArray(JSContext *cx);
|
2010-10-29 08:05:55 -07:00
|
|
|
|
|
|
|
/* Resolve pending type registrations, excluding delayed ones. */
|
|
|
|
inline void resolvePending(JSContext *cx);
|
|
|
|
|
2010-11-18 15:18:23 -08:00
|
|
|
/* Prints results of this compartment if spew is enabled, checks for warnings. */
|
2011-03-10 16:17:39 -08:00
|
|
|
void print(JSContext *cx, JSCompartment *compartment);
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2010-12-18 20:44:51 -08:00
|
|
|
/* Make a function or non-function object associated with an optional script. */
|
2011-03-01 13:10:05 -08:00
|
|
|
TypeObject *newTypeObject(JSContext *cx, JSScript *script,
|
2011-04-05 18:12:03 -07:00
|
|
|
const char *name, bool isFunction, bool isArray, JSObject *proto);
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2010-12-28 11:53:50 -08:00
|
|
|
/* Make an initializer object. */
|
|
|
|
TypeObject *newInitializerTypeObject(JSContext *cx, JSScript *script,
|
|
|
|
uint32 offset, bool isArray);
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/*
|
2010-11-15 18:13:05 -08:00
|
|
|
* Add the specified type to the specified set, do any necessary reanalysis
|
|
|
|
* stemming from the change and recompile any affected scripts.
|
2010-10-29 08:05:55 -07:00
|
|
|
*/
|
2011-03-03 14:07:48 -08:00
|
|
|
bool dynamicPush(JSContext *cx, JSScript *script, uint32 offset, jstype type);
|
|
|
|
bool dynamicAssign(JSContext *cx, JSObject *obj, jsid id, const Value &rval);
|
|
|
|
bool dynamicCall(JSContext *cx, JSObject *callee, const CallArgs &args, bool constructing);
|
|
|
|
|
|
|
|
inline bool checkPendingRecompiles(JSContext *cx);
|
|
|
|
|
|
|
|
bool nukeTypes(JSContext *cx);
|
|
|
|
bool processPendingRecompiles(JSContext *cx);
|
|
|
|
|
|
|
|
/* Mark all types as needing destruction once inference has 'finished'. */
|
|
|
|
void setPendingNukeTypes(JSContext *cx);
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2011-03-03 14:07:48 -08:00
|
|
|
/* Mark a script as needing recompilation once inference has finished. */
|
2010-11-18 08:28:05 -08:00
|
|
|
void addPendingRecompile(JSContext *cx, JSScript *script);
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
/* Monitor future effects on a bytecode. */
|
2010-12-28 11:53:50 -08:00
|
|
|
void monitorBytecode(JSContext *cx, JSScript *script, uint32 offset);
|
2010-10-29 08:05:55 -07:00
|
|
|
|
2011-03-09 09:58:49 -08:00
|
|
|
void condense(JSContext *cx);
|
|
|
|
void sweep(JSContext *cx);
|
|
|
|
};
|
2011-03-01 13:10:05 -08:00
|
|
|
|
2010-11-18 15:18:23 -08:00
|
|
|
enum SpewChannel {
|
|
|
|
ISpewOps, /* ops: New constraints and types. */
|
|
|
|
ISpewResult, /* result: Final type sets. */
|
|
|
|
SPEW_COUNT
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
void InferSpew(SpewChannel which, const char *fmt, ...);
|
2010-11-20 15:45:52 -08:00
|
|
|
const char * TypeString(jstype type);
|
2010-11-18 15:18:23 -08:00
|
|
|
|
2011-03-06 15:35:09 -08:00
|
|
|
/* Check that the type property for id in obj contains value. */
|
|
|
|
bool TypeHasProperty(JSContext *cx, TypeObject *obj, jsid id, const Value &value);
|
|
|
|
|
2010-11-18 15:18:23 -08:00
|
|
|
#else
|
|
|
|
|
|
|
|
inline void InferSpew(SpewChannel which, const char *fmt, ...) {}
|
2010-11-20 15:45:52 -08:00
|
|
|
inline const char * TypeString(jstype type) { return NULL; }
|
2010-11-18 15:18:23 -08:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2010-11-20 15:45:52 -08:00
|
|
|
/* Print a warning, dump state and abort the program. */
|
|
|
|
void TypeFailure(JSContext *cx, const char *fmt, ...);
|
|
|
|
|
2010-10-29 08:05:55 -07:00
|
|
|
} /* namespace types */
|
|
|
|
} /* namespace js */
|
|
|
|
|
|
|
|
static JS_ALWAYS_INLINE js::types::TypeObject *
|
|
|
|
Valueify(JSTypeObject *jstype) { return (js::types::TypeObject*) jstype; }
|
|
|
|
|
|
|
|
static JS_ALWAYS_INLINE js::types::TypeFunction *
|
|
|
|
Valueify(JSTypeFunction *jstype) { return (js::types::TypeFunction*) jstype; }
|
|
|
|
|
|
|
|
static JS_ALWAYS_INLINE js::types::TypeCallsite *
|
|
|
|
Valueify(JSTypeCallsite *jssite) { return (js::types::TypeCallsite*) jssite; }
|
|
|
|
|
|
|
|
#endif // jsinfer_h___
|