bool MarkInnerAndOuterFunctions(JSContext *cx, JSScript* script_) { Rooted<JSScript*> script(cx, script_); Vector<JSScript *, 16> worklist(cx); if (!worklist.append(script.reference())) return false; while (worklist.length()) { JSScript *outer = worklist.back(); worklist.popBack(); /* * If outer has an extensible scope, its slots may be resized which * will invalidate nesting->varArray/argArray. */ if (outer->funHasExtensibleScope) continue; if (outer->hasObjects()) { ObjectArray *arr = outer->objects(); /* * If this is an eval script, don't treat the saved caller function * stored in the first object slot as an inner function. */ size_t start = outer->savedCallerFun ? 1 : 0; for (size_t i = start; i < arr->length; i++) { JSObject *obj = arr->vector[i]; if (!obj->isFunction()) continue; JSFunction *fun = obj->toFunction(); JS_ASSERT(fun->isInterpreted()); JSScript *inner = fun->script(); if (outer->function() && outer->function()->isHeavyweight()) { outer->isOuterFunction = true; inner->isInnerFunction = true; } if (!inner->hasObjects()) continue; if (!worklist.append(inner)) return false; } } } return true; }
bool MarkInnerAndOuterFunctions(JSContext *cx, JSScript* script) { Root<JSScript*> root(cx, &script); Vector<JSScript *, 16> worklist(cx); if (!worklist.append(script)) return false; while (worklist.length()) { JSScript *outer = worklist.back(); worklist.popBack(); if (outer->hasObjects()) { ObjectArray *arr = outer->objects(); /* * If this is an eval script, don't treat the saved caller function * stored in the first object slot as an inner function. */ size_t start = outer->savedCallerFun ? 1 : 0; for (size_t i = start; i < arr->length; i++) { JSObject *obj = arr->vector[i]; if (!obj->isFunction()) continue; JSFunction *fun = obj->toFunction(); JS_ASSERT(fun->isInterpreted()); JSScript *inner = fun->script(); if (outer->function() && outer->function()->isHeavyweight()) { outer->isOuterFunction = true; inner->isInnerFunction = true; } if (!inner->hasObjects()) continue; if (!worklist.append(inner)) return false; } } } return true; }
void ion::HandleException(ResumeFromException *rfe) { JSContext *cx = GetIonContext()->cx; IonSpew(IonSpew_Invalidate, "handling exception"); // Immediately remove any bailout frame guard that might be left over from // an error in between ConvertFrames and ThunkToInterpreter. js_delete(cx->runtime->ionActivation->maybeTakeBailout()); IonFrameIterator iter(cx->runtime->ionTop); while (!iter.isEntry()) { if (iter.isScripted()) { // Search each inlined frame for live iterator objects, and close // them. InlineFrameIterator frames(&iter); for (;;) { CloseLiveIterators(cx, frames); // When profiling, each frame popped needs a notification that // the function has exited, so invoke the probe that a function // is exiting. JSScript *script = frames.script(); Probes::exitScript(cx, script, script->function(), NULL); if (!frames.more()) break; ++frames; } IonScript *ionScript; if (iter.checkInvalidation(&ionScript)) ionScript->decref(cx->runtime->defaultFreeOp()); } ++iter; } // Clear any Ion return override that's been set. // This may happen if a callVM function causes an invalidation (setting the // override), and then fails, bypassing the bailout handlers that would // otherwise clear the return override. if (cx->runtime->hasIonReturnOverride()) cx->runtime->takeIonReturnOverride(); rfe->stackPointer = iter.fp(); }
static JSBool ArgSetter(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, Value *vp) { if (!obj->isNormalArguments()) return true; NormalArgumentsObject &argsobj = obj->asNormalArguments(); JSScript *script = argsobj.containingScript(); if (JSID_IS_INT(id)) { unsigned arg = unsigned(JSID_TO_INT(id)); if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg)) { argsobj.setElement(arg, *vp); if (arg < script->function()->nargs) { if (!script->ensureHasTypes(cx)) return false; types::TypeScript::SetArgument(cx, script, arg, *vp); } return true; } } else { JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom) || JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom)); } /* * For simplicity we use delete/define to replace the property with one * backed by the default Object getter and setter. Note that we rely on * args_delProperty to clear the corresponding reserved slot so the GC can * collect its value. Note also that we must define the property instead * of setting it in case the user has changed the prototype to an object * that has a setter for this id. */ RootedValue value(cx); return baseops::DeleteGeneric(cx, obj, id, value.address(), false) && baseops::DefineProperty(cx, obj, id, vp, NULL, NULL, JSPROP_ENUMERATE); }
bool DefineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *script) { JSObject *globalObj = globalScope.globalObj; /* Define and update global properties. */ for (size_t i = 0; i < globalScope.defs.length(); i++) { GlobalScope::GlobalDef &def = globalScope.defs[i]; /* Names that could be resolved ahead of time can be skipped. */ if (!def.atom) continue; jsid id = ATOM_TO_JSID(def.atom); Value rval; if (def.funbox) { JSFunction *fun = def.funbox->function(); /* * No need to check for redeclarations or anything, global * optimizations only take place if the property is not defined. */ rval.setObject(*fun); types::AddTypePropertyId(cx, globalObj, id, rval); } else { rval.setUndefined(); } /* * Don't update the type information when defining the property for the * global object, per the consistency rules for type properties. If the * property is only undefined before it is ever written, we can check * the global directly during compilation and avoid having to emit type * checks every time it is accessed in the script. */ const Shape *shape = DefineNativeProperty(cx, globalObj, id, rval, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE | JSPROP_PERMANENT, 0, 0, DNP_SKIP_TYPE); if (!shape) return false; def.knownSlot = shape->slot(); } Vector<JSScript *, 16> worklist(cx); if (!worklist.append(script)) return false; /* * Recursively walk through all scripts we just compiled. For each script, * go through all global uses. Each global use indexes into globalScope->defs. * Use this information to repoint each use to the correct slot in the global * object. */ while (worklist.length()) { JSScript *outer = worklist.back(); worklist.popBack(); if (JSScript::isValidOffset(outer->objectsOffset)) { JSObjectArray *arr = outer->objects(); /* * If this is an eval script, don't treat the saved caller function * stored in the first object slot as an inner function. */ size_t start = outer->savedCallerFun ? 1 : 0; for (size_t i = start; i < arr->length; i++) { JSObject *obj = arr->vector[i]; if (!obj->isFunction()) continue; JSFunction *fun = obj->toFunction(); JS_ASSERT(fun->isInterpreted()); JSScript *inner = fun->script(); if (outer->function() && outer->function()->isHeavyweight()) { outer->isOuterFunction = true; inner->isInnerFunction = true; } if (!JSScript::isValidOffset(inner->globalsOffset) && !JSScript::isValidOffset(inner->objectsOffset)) { continue; } if (!worklist.append(inner)) return false; } } if (!JSScript::isValidOffset(outer->globalsOffset)) continue; GlobalSlotArray *globalUses = outer->globals(); uint32_t nGlobalUses = globalUses->length; for (uint32_t i = 0; i < nGlobalUses; i++) { uint32_t index = globalUses->vector[i].slot; JS_ASSERT(index < globalScope.defs.length()); globalUses->vector[i].slot = globalScope.defs[index].knownSlot; } } return true; }