Merge inbound to m-c

This commit is contained in:
Wes Kocher 2014-02-26 18:20:47 -08:00
commit a9f65835bc
39 changed files with 5169 additions and 178 deletions

View File

@ -804,9 +804,7 @@ pref("browser.safebrowsing.reportMalwareURL", "http://%LOCALE%.malware-report.mo
pref("browser.safebrowsing.reportMalwareErrorURL", "http://%LOCALE%.malware-error.mozilla.com/?hl=%LOCALE%");
pref("browser.safebrowsing.malware.reportURL", "https://safebrowsing.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
#ifndef MOZILLA_OFFICIAL
pref("browser.safebrowsing.appRepURL", "https://sb-ssl.google.com/safebrowsing/clientreport/download&key=%GOOGLE_API_KEY%");
#endif
#ifdef MOZILLA_OFFICIAL
// Normally the "client ID" sent in updates is appinfo.name, but for
@ -827,8 +825,13 @@ pref("urlclassifier.gethashnoise", 4);
pref("urlclassifier.max-complete-age", 2700);
// Tables for application reputation.
pref("urlclassifier.download_block_table", "goog-badbinurl-shavar");
#ifdef XP_WIN
// Only download the whitelist on Windows, since the whitelist is
// only useful for suppressing remote lookups for signed binaries which we can
// only verify on Windows (Bug 974579).
pref("urlclassifier.download_allow_table", "goog-downloadwhite-digest256");
#endif
#endif
pref("browser.geolocation.warning.infoURL", "https://www.mozilla.org/%LOCALE%/firefox/geolocation/");

View File

@ -17,6 +17,7 @@ gyp_vars = {
'enable_protobuf': 0,
'include_tests': 0,
'enable_android_opensl': 1,
'enable_android_opensl_output': 0,
# use_system_lib* still seems to be in use in trunk/build
'use_system_libjpeg': 0,
'use_system_libvpx': 0,

View File

@ -22,7 +22,6 @@
#include "mozilla/dom/RootedDictionary.h"
#include "mozilla/dom/workers/Workers.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/HoldDropJSObjects.h"
#include "mozilla/Likely.h"
#include "mozilla/MemoryReporting.h"
#include "nsCycleCollector.h"
@ -2427,7 +2426,9 @@ CreateGlobal(JSContext* aCx, T* aObject, nsWrapperCache* aCache,
return nullptr;
}
mozilla::HoldJSObjects(aObject);
MOZ_ALWAYS_TRUE(TryPreserveWrapper(global));
MOZ_ASSERT(UnwrapDOMObjectToISupports(global));
return global;
}

View File

@ -299,7 +299,8 @@ def UseHolderForUnforgeable(descriptor):
descriptor.proxy and
any(m for m in descriptor.interface.members if m.isAttr() and m.isUnforgeable()))
def CallOnUnforgeableHolder(descriptor, code, isXrayCheck=None):
def CallOnUnforgeableHolder(descriptor, code, isXrayCheck=None,
useSharedRoot=False):
"""
Generate the code to execute the code in "code" on an unforgeable holder if
needed. code should be a string containing the code to execute. If it
@ -309,6 +310,10 @@ def CallOnUnforgeableHolder(descriptor, code, isXrayCheck=None):
If isXrayCheck is not None it should be a string that contains a statement
returning whether proxy is an Xray. If isXrayCheck is None the generated
code won't try to unwrap Xrays.
If useSharedRoot is true, we will use an existing
JS::Rooted<JSObject*> sharedRoot for storing our unforgeable holder instead
of declaring a new Rooted.
"""
code = string.Template(code).substitute({ "holder": "unforgeableHolder" })
if not isXrayCheck is None:
@ -327,11 +332,16 @@ def CallOnUnforgeableHolder(descriptor, code, isXrayCheck=None):
{
JSObject* global = js::GetGlobalForObjectCrossCompartment(proxy);"""
if useSharedRoot:
holderDecl = "JS::Rooted<JSObject*>& unforgeableHolder(sharedRoot)"
else:
holderDecl = "JS::Rooted<JSObject*> unforgeableHolder(cx)"
return (pre + """
JS::Rooted<JSObject*> unforgeableHolder(cx, GetUnforgeableHolder(global, prototypes::id::%s));
%s;
unforgeableHolder = GetUnforgeableHolder(global, prototypes::id::%s);
""" + CGIndenter(CGGeneric(code)).define() + """
}
""") % descriptor.name
""") % (holderDecl, descriptor.name)
class CGPrototypeJSClass(CGThing):
def __init__(self, descriptor, properties):
@ -4778,21 +4788,9 @@ def getRetvalDeclarationForType(returnType, descriptorProvider,
name = returnType.unroll().identifier.name
return CGGeneric("nsRefPtr<%s>" % name), False, None, None
if returnType.isAny():
result = CGGeneric("JS::Value")
if isMember:
resultArgs = None
else:
result = CGTemplatedType("JS::Rooted", result)
resultArgs = "cx"
return result, False, None, resultArgs
return CGGeneric("JS::Value"), False, None, None
if returnType.isObject() or returnType.isSpiderMonkeyInterface():
result = CGGeneric("JSObject*")
if isMember:
resultArgs = None
else:
result = CGTemplatedType("JS::Rooted", result)
resultArgs = "cx"
return result, False, None, resultArgs
return CGGeneric("JSObject*"), False, None, None
if returnType.isSequence():
nullable = returnType.nullable()
if nullable:
@ -8543,6 +8541,7 @@ class CGDOMJSProxyHandler_get(ClassMethod):
ClassMethod.__init__(self, "get", "bool", args)
self.descriptor = descriptor
def getBody(self):
getUnforgeableOrExpando = "JS::Rooted<JSObject*> sharedRoot(cx);\n"
if UseHolderForUnforgeable(self.descriptor):
hasUnforgeable = (
"bool hasUnforgeable;\n"
@ -8552,21 +8551,23 @@ class CGDOMJSProxyHandler_get(ClassMethod):
"if (hasUnforgeable) {\n"
" return JS_ForwardGetPropertyTo(cx, ${holder}, id, proxy, vp);\n"
"}")
getUnforgeableOrExpando = CallOnUnforgeableHolder(self.descriptor,
hasUnforgeable)
else:
getUnforgeableOrExpando = ""
getUnforgeableOrExpando += """JS::Rooted<JSObject*> expando(cx, DOMProxyHandler::GetExpandoObject(proxy));
if (expando) {
bool hasProp;
if (!JS_HasPropertyById(cx, expando, id, &hasProp)) {
return false;
}
getUnforgeableOrExpando += CallOnUnforgeableHolder(self.descriptor,
hasUnforgeable,
useSharedRoot=True)
getUnforgeableOrExpando += """{ // Scope for expando
JS::Rooted<JSObject*>& expando(sharedRoot);
expando = DOMProxyHandler::GetExpandoObject(proxy);
if (expando) {
bool hasProp;
if (!JS_HasPropertyById(cx, expando, id, &hasProp)) {
return false;
}
if (hasProp) {
// Forward the get to the expando object, but our receiver is whatever our
// receiver is.
return JS_ForwardGetPropertyTo(cx, expando, id, receiver, vp);
if (hasProp) {
// Forward the get to the expando object, but our receiver is whatever our
// receiver is.
return JS_ForwardGetPropertyTo(cx, expando, id, receiver, vp);
}
}
}"""

View File

@ -260,8 +260,8 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(StackDescriptionOwner)
JS::StackDescription* desc = tmp->mDescription;
if (tmp->mDescription) {
for (size_t i = 0; i < desc->nframes; ++i) {
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDescription->frames[i].script());
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDescription->frames[i].fun());
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDescription->frames[i].markedLocation1());
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDescription->frames[i].markedLocation2());
}
}
NS_IMPL_CYCLE_COLLECTION_TRACE_END
@ -377,13 +377,8 @@ NS_IMETHODIMP JSStackFrame::GetFilename(nsACString& aFilename)
{
if (!mFilenameInitialized) {
JS::FrameDescription& desc = mStackDescription->FrameAt(mIndex);
if (desc.script()) {
ThreadsafeAutoSafeJSContext cx;
JSAutoCompartment ac(cx, desc.script());
const char* filename = JS_GetScriptFilename(cx, desc.script());
if (filename) {
mFilename.Assign(filename);
}
if (const char *filename = desc.filename()) {
mFilename.Assign(filename);
}
mFilenameInitialized = true;
}
@ -403,14 +398,8 @@ NS_IMETHODIMP JSStackFrame::GetName(nsACString& aFunction)
{
if (!mFunnameInitialized) {
JS::FrameDescription& desc = mStackDescription->FrameAt(mIndex);
if (desc.fun() && desc.script()) {
ThreadsafeAutoSafeJSContext cx;
JSAutoCompartment ac(cx, desc.script());
JS::Rooted<JSFunction*> fun(cx, desc.fun());
JS::Rooted<JSString*> funid(cx, JS_GetFunctionDisplayId(fun));
if (funid) {
CopyUTF16toUTF8(JS_GetStringCharsZ(cx, funid), mFunname);
}
if (JSFlatString *name = desc.funDisplayName()) {
CopyUTF16toUTF8(JS_GetFlatStringChars(name), mFunname);
}
mFunnameInitialized = true;
}

View File

@ -217,7 +217,7 @@ WrapperPromiseCallback::Call(JS::Handle<JS::Value> aValue)
MOZ_ASSERT(func);
JSScript* script = JS_GetFunctionScript(cx, func);
if (script) {
fileName = JS_GetScriptFilename(cx, script);
fileName = JS_GetScriptFilename(script);
lineNumber = JS_GetScriptBaseLineNumber(cx, script);
}
}

View File

@ -8,16 +8,25 @@
*/
interface MutationRecord {
[Constant]
readonly attribute DOMString type;
// .target is not nullable per the spec, but in order to prevent crashes,
// if there are GC/CC bugs in Gecko, we let the property to be null.
[Constant]
readonly attribute Node? target;
[Constant]
readonly attribute NodeList addedNodes;
[Constant]
readonly attribute NodeList removedNodes;
[Constant]
readonly attribute Node? previousSibling;
[Constant]
readonly attribute Node? nextSibling;
[Constant]
readonly attribute DOMString? attributeName;
[Constant]
readonly attribute DOMString? attributeNamespace;
[Constant]
readonly attribute DOMString? oldValue;
};

View File

@ -42,8 +42,7 @@ WorkerGlobalScope::WorkerGlobalScope(WorkerPrivate* aWorkerPrivate)
WorkerGlobalScope::~WorkerGlobalScope()
{
// Matches the HoldJSObjects in CreateGlobal.
mozilla::DropJSObjects(this);
mWorkerPrivate->AssertIsOnWorkerThread();
}
NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerGlobalScope)

View File

@ -456,9 +456,16 @@ Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
if (!segment)
return 0;
Header* header = GetHeader(segment);
if (size != header->mSize) {
NS_ERROR("Wrong size for this Shmem!");
delete segment;
return nullptr;
}
// The caller of this function may not know whether the segment is
// unsafe or not
Header* header = GetHeader(segment);
if (!header->mUnsafe && aProtect)
Protect(segment);
@ -571,8 +578,9 @@ Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
if (!segment)
return 0;
// this is the only validity check done OPT builds
// this is the only validity check done in non-DEBUG builds
if (size != static_cast<size_t>(*PtrToSize(segment))) {
delete segment;
return nullptr;
}

View File

@ -97,7 +97,7 @@ jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
script = frame.script();
if( script )
{
ctorURL = JS_GetScriptFilename(cx, script);
ctorURL = JS_GetScriptFilename(script);
if( ctorURL )
jsdobj->ctorURL = jsd_AddAtom(jsdc, ctorURL);

View File

@ -62,7 +62,7 @@ _newJSDScript(JSDContext* jsdc,
if( ! jsdscript )
return nullptr;
raw_filename = JS_GetScriptFilename(cx,script);
raw_filename = JS_GetScriptFilename(script);
JS_HashTableAdd(jsdc->scriptsTable, (void *)script, (void *)jsdscript);
JS_APPEND_LINK(&jsdscript->links, &jsdc->scripts);

View File

@ -13,6 +13,7 @@
#include "mozilla/NullPtr.h"
#include "jsapi.h"
#include "jsbytecode.h"
#include "js/CallArgs.h"
@ -30,19 +31,14 @@ class ScriptFrameIter;
extern JS_PUBLIC_API(unsigned)
JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
extern JS_PUBLIC_API(const char *)
JS_GetScriptFilename(JSScript *script);
namespace JS {
class FrameDescription
{
public:
FrameDescription(JSScript *script, JSFunction *fun, jsbytecode *pc)
: script_(script)
, fun_(fun)
, pc_(pc)
, linenoComputed(false)
{
}
explicit FrameDescription(const js::ScriptFrameIter& iter);
unsigned lineno() {
@ -53,17 +49,26 @@ class FrameDescription
return lineno_;
}
Heap<JSScript*> &script() {
return script_;
const char *filename() const {
return JS_GetScriptFilename(script_);
}
Heap<JSFunction*> &fun() {
return fun_;
JSFlatString *funDisplayName() const {
return funDisplayName_ ? JS_ASSERT_STRING_IS_FLAT(funDisplayName_) : nullptr;
}
// Both these locations should be traced during GC but otherwise not used;
// they are implementation details.
Heap<JSScript*> &markedLocation1() {
return script_;
}
Heap<JSString*> &markedLocation2() {
return funDisplayName_;
}
private:
Heap<JSScript*> script_;
Heap<JSFunction*> fun_;
Heap<JSString*> funDisplayName_;
jsbytecode *pc_;
unsigned lineno_;
bool linenoComputed;
@ -297,9 +302,6 @@ JS_GetDebugClassName(JSObject *obj);
/************************************************************************/
extern JS_PUBLIC_API(const char *)
JS_GetScriptFilename(JSContext *cx, JSScript *script);
extern JS_PUBLIC_API(const jschar *)
JS_GetScriptSourceMap(JSContext *cx, JSScript *script);

View File

@ -35,3 +35,10 @@ assertEq(h2(), 1);
assertEq(h1(), 3);
assertEq(h2(), 2);
assertEq(h1(), 4);
var code = asmCompile(USE_ASM + "return {}");
var h1 = code();
var h2 = code();
assertEq(h1 === h2, false);
assertEq(Object.keys(h1).length, 0);
assertEq(Object.keys(h2).length, 0);

View File

@ -907,6 +907,11 @@ AsmJSModule::protectCode(JSRuntime *rt) const
{
JS_ASSERT(rt->currentThreadOwnsOperationCallbackLock());
codeIsProtected_ = true;
if (!pod.functionBytes_)
return;
// Technically, we should be able to only take away the execute permissions,
// however this seems to break our emulators which don't always check
// execute permissions while executing code.
@ -918,13 +923,18 @@ AsmJSModule::protectCode(JSRuntime *rt) const
if (mprotect(codeBase(), functionBytes(), PROT_NONE))
MOZ_CRASH();
#endif
codeIsProtected_ = true;
}
void
AsmJSModule::unprotectCode(JSRuntime *rt) const
{
JS_ASSERT(rt->currentThreadOwnsOperationCallbackLock());
codeIsProtected_ = false;
if (!pod.functionBytes_)
return;
#if defined(XP_WIN)
DWORD oldProtect;
if (!VirtualProtect(codeBase(), functionBytes(), PAGE_EXECUTE_READWRITE, &oldProtect))
@ -933,8 +943,6 @@ AsmJSModule::unprotectCode(JSRuntime *rt) const
if (mprotect(codeBase(), functionBytes(), PROT_READ | PROT_WRITE | PROT_EXEC))
MOZ_CRASH();
#endif
codeIsProtected_ = false;
}
bool

View File

@ -417,7 +417,7 @@ class AsmJSModule
FunctionCountsVector functionCounts_;
// This field is accessed concurrently when triggering the operation
// callback and access must be sychronized via the runtime's operation
// callback and access must be synchronized via the runtime's operation
// callback lock.
mutable bool codeIsProtected_;

View File

@ -458,6 +458,8 @@ HandleException(PEXCEPTION_POINTERS exception)
if (module.containsPC(faultingAddress)) {
activation->setResumePC(pc);
*ppc = module.operationCallbackExit();
JSRuntime::AutoLockForOperationCallback lock(rt);
module.unprotectCode(rt);
return true;
}
@ -643,6 +645,7 @@ HandleMachException(JSRuntime *rt, const ExceptionRequest &request)
const AsmJSModule &module = activation->module();
if (HandleSimulatorInterrupt(rt, activation, faultingAddress)) {
JSRuntime::AutoLockForOperationCallback lock(rt);
module.unprotectCode(rt);
return true;
}
@ -658,6 +661,8 @@ HandleMachException(JSRuntime *rt, const ExceptionRequest &request)
if (module.containsPC(faultingAddress)) {
activation->setResumePC(pc);
*ppc = module.operationCallbackExit();
JSRuntime::AutoLockForOperationCallback lock(rt);
module.unprotectCode(rt);
// Update the thread state with the new pc.
@ -890,6 +895,7 @@ HandleSignal(int signum, siginfo_t *info, void *ctx)
const AsmJSModule &module = activation->module();
if (HandleSimulatorInterrupt(rt, activation, faultingAddress)) {
JSRuntime::AutoLockForOperationCallback lock(rt);
module.unprotectCode(rt);
return true;
}
@ -905,6 +911,8 @@ HandleSignal(int signum, siginfo_t *info, void *ctx)
if (module.containsPC(faultingAddress)) {
activation->setResumePC(pc);
*ppc = module.operationCallbackExit();
JSRuntime::AutoLockForOperationCallback lock(rt);
module.unprotectCode(rt);
return true;
}

View File

@ -565,9 +565,9 @@ Assembler::as_bal(BOffImm16 off)
}
InstImm
Assembler::getBranchCode(bool isCall)
Assembler::getBranchCode(JumpOrCall jumpOrCall)
{
if (isCall)
if (jumpOrCall == BranchIsCall)
return InstImm(op_regimm, zero, rt_bgezal, BOffImm16(0));
return InstImm(op_beq, zero, zero, BOffImm16(0));
@ -608,10 +608,10 @@ Assembler::getBranchCode(Register s, Condition c)
}
InstImm
Assembler::getBranchCode(bool testTrue, FPConditionBit fcc)
Assembler::getBranchCode(FloatTestKind testKind, FPConditionBit fcc)
{
JS_ASSERT(!(fcc && FccMask));
uint32_t rtField = ((testTrue ? 1 : 0) | (fcc << FccShift)) << RTShift;
uint32_t rtField = ((testKind == TestForTrue ? 1 : 0) | (fcc << FccShift)) << RTShift;
return InstImm(op_cop1, rs_bc1, rtField, BOffImm16(0));
}
@ -1172,100 +1172,61 @@ Assembler::as_sqrtd(FloatRegister fd, FloatRegister fs)
// FP compare instructions
BufferOffset
Assembler::as_cfs(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
Assembler::as_cf(FloatFormat fmt, FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_s, ft, fs, fcc << FccShift, ff_c_f_fmt).encode());
RSField rs = fmt == DoubleFloat ? rs_d : rs_s;
return writeInst(InstReg(op_cop1, rs, ft, fs, fcc << FccShift, ff_c_f_fmt).encode());
}
BufferOffset
Assembler::as_cuns(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
Assembler::as_cun(FloatFormat fmt, FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_s, ft, fs, fcc << FccShift, ff_c_un_fmt).encode());
RSField rs = fmt == DoubleFloat ? rs_d : rs_s;
return writeInst(InstReg(op_cop1, rs, ft, fs, fcc << FccShift, ff_c_un_fmt).encode());
}
BufferOffset
Assembler::as_ceqs(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
Assembler::as_ceq(FloatFormat fmt, FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_s, ft, fs, fcc << FccShift, ff_c_eq_fmt).encode());
RSField rs = fmt == DoubleFloat ? rs_d : rs_s;
return writeInst(InstReg(op_cop1, rs, ft, fs, fcc << FccShift, ff_c_eq_fmt).encode());
}
BufferOffset
Assembler::as_cueqs(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
Assembler::as_cueq(FloatFormat fmt, FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_s, ft, fs, fcc << FccShift, ff_c_ueq_fmt).encode());
RSField rs = fmt == DoubleFloat ? rs_d : rs_s;
return writeInst(InstReg(op_cop1, rs, ft, fs, fcc << FccShift, ff_c_ueq_fmt).encode());
}
BufferOffset
Assembler::as_colts(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
Assembler::as_colt(FloatFormat fmt, FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_s, ft, fs, fcc << FccShift, ff_c_olt_fmt).encode());
RSField rs = fmt == DoubleFloat ? rs_d : rs_s;
return writeInst(InstReg(op_cop1, rs, ft, fs, fcc << FccShift, ff_c_olt_fmt).encode());
}
BufferOffset
Assembler::as_cults(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
Assembler::as_cult(FloatFormat fmt, FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_s, ft, fs, fcc << FccShift, ff_c_ult_fmt).encode());
RSField rs = fmt == DoubleFloat ? rs_d : rs_s;
return writeInst(InstReg(op_cop1, rs, ft, fs, fcc << FccShift, ff_c_ult_fmt).encode());
}
BufferOffset
Assembler::as_coles(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
Assembler::as_cole(FloatFormat fmt, FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_s, ft, fs, fcc << FccShift, ff_c_ole_fmt).encode());
RSField rs = fmt == DoubleFloat ? rs_d : rs_s;
return writeInst(InstReg(op_cop1, rs, ft, fs, fcc << FccShift, ff_c_ole_fmt).encode());
}
BufferOffset
Assembler::as_cules(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
Assembler::as_cule(FloatFormat fmt, FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_s, ft, fs, fcc << FccShift, ff_c_ule_fmt).encode());
RSField rs = fmt == DoubleFloat ? rs_d : rs_s;
return writeInst(InstReg(op_cop1, rs, ft, fs, fcc << FccShift, ff_c_ule_fmt).encode());
}
BufferOffset
Assembler::as_cfd(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_d, ft, fs, fcc << FccShift, ff_c_f_fmt).encode());
}
BufferOffset
Assembler::as_cund(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_d, ft, fs, fcc << FccShift, ff_c_un_fmt).encode());
}
BufferOffset
Assembler::as_ceqd(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_d, ft, fs, fcc << FccShift, ff_c_eq_fmt).encode());
}
BufferOffset
Assembler::as_cueqd(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_d, ft, fs, fcc << FccShift, ff_c_ueq_fmt).encode());
}
BufferOffset
Assembler::as_coltd(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_d, ft, fs, fcc << FccShift, ff_c_olt_fmt).encode());
}
BufferOffset
Assembler::as_cultd(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_d, ft, fs, fcc << FccShift, ff_c_ult_fmt).encode());
}
BufferOffset
Assembler::as_coled(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_d, ft, fs, fcc << FccShift, ff_c_ole_fmt).encode());
}
BufferOffset
Assembler::as_culed(FloatRegister fs, FloatRegister ft, FPConditionBit fcc)
{
return writeInst(InstReg(op_cop1, rs_d, ft, fs, fcc << FccShift, ff_c_ule_fmt).encode());
}
void
Assembler::bind(Label *label, BufferOffset boff)

View File

@ -617,6 +617,21 @@ class Assembler
FCC7
};
enum FloatFormat {
SingleFloat,
DoubleFloat
};
enum JumpOrCall {
BranchIsJump,
BranchIsCall
};
enum FloatTestKind {
TestForTrue,
TestForFalse
};
// :( this should be protected, but since CodeGenerator
// wants to use it, It needs to go out here :(
@ -750,10 +765,10 @@ class Assembler
// Branch and jump instructions
BufferOffset as_bal(BOffImm16 off);
InstImm getBranchCode(bool isCall);
InstImm getBranchCode(JumpOrCall jumpOrCall);
InstImm getBranchCode(Register s, Register t, Condition c);
InstImm getBranchCode(Register s, Condition c);
InstImm getBranchCode(bool testTrue, FPConditionBit fcc);
InstImm getBranchCode(FloatTestKind testKind, FPConditionBit fcc);
BufferOffset as_j(JOffImm26 off);
BufferOffset as_jal(JOffImm26 off);
@ -895,24 +910,22 @@ class Assembler
BufferOffset as_sqrtd(FloatRegister fd, FloatRegister fs);
// FP compare instructions
BufferOffset as_cfs(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_cuns(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_ceqs(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_cueqs(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_colts(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_cults(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_coles(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_cules(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_cfd(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_cund(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_ceqd(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_cueqd(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_coltd(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_cultd(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_coled(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_culed(FloatRegister fs, FloatRegister ft, FPConditionBit fcc = FCC0);
BufferOffset as_cf(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
FPConditionBit fcc = FCC0);
BufferOffset as_cun(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
FPConditionBit fcc = FCC0);
BufferOffset as_ceq(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
FPConditionBit fcc = FCC0);
BufferOffset as_cueq(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
FPConditionBit fcc = FCC0);
BufferOffset as_colt(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
FPConditionBit fcc = FCC0);
BufferOffset as_cult(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
FPConditionBit fcc = FCC0);
BufferOffset as_cole(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
FPConditionBit fcc = FCC0);
BufferOffset as_cule(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
FPConditionBit fcc = FCC0);
// label operations
void bind(Label *label, BufferOffset boff = BufferOffset());

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -38,7 +38,7 @@ BEGIN_TEST(testScriptInfo)
CHECK_EQUAL(JS_GetScriptBaseLineNumber(cx, script), startLine);
CHECK_EQUAL(JS_PCToLineNumber(cx, script, start), startLine);
CHECK_EQUAL(JS_GetScriptLineExtent(cx, script), 11);
CHECK(strcmp(JS_GetScriptFilename(cx, script), __FILE__) == 0);
CHECK(strcmp(JS_GetScriptFilename(script), __FILE__) == 0);
const jschar *sourceMap = JS_GetScriptSourceMap(cx, script);
CHECK(sourceMap);
CHECK(CharsMatch(sourceMap, "http://example.com/path/to/source-map.json"));

View File

@ -5884,7 +5884,7 @@ js_DumpBacktrace(JSContext *cx)
sprinter.init();
size_t depth = 0;
for (ScriptFrameIter i(cx); !i.done(); ++i, ++depth) {
const char *filename = JS_GetScriptFilename(cx, i.script());
const char *filename = JS_GetScriptFilename(i.script());
unsigned line = JS_PCToLineNumber(cx, i.script(), i.pc());
JSScript *script = i.script();
sprinter.printf("#%d %14p %s:%d (%p @ %d)\n",

View File

@ -555,7 +555,7 @@ JS_GetDebugClassName(JSObject *obj)
/************************************************************************/
JS_PUBLIC_API(const char *)
JS_GetScriptFilename(JSContext *cx, JSScript *script)
JS_GetScriptFilename(JSScript *script)
{
return script->filename();
}
@ -925,7 +925,14 @@ js_CallContextDebugHandler(JSContext *cx)
* FrameDescription contains Heap<T> fields that should not live on the stack.
*/
JS::FrameDescription::FrameDescription(const ScriptFrameIter& iter)
: script_(iter.script()), fun_(iter.maybeCallee()), pc_(iter.pc()), linenoComputed(false) {}
: script_(iter.script()),
funDisplayName_(nullptr),
pc_(iter.pc()),
linenoComputed(false)
{
if (JSFunction *fun = iter.maybeCallee())
funDisplayName_ = fun->displayAtom();
}
JS_PUBLIC_API(JS::StackDescription *)
JS::DescribeStack(JSContext *cx, unsigned maxFrames)

View File

@ -16,8 +16,13 @@
namespace webrtc {
AudioDeviceAndroidOpenSLES::AudioDeviceAndroidOpenSLES(const int32_t id)
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
: output_(id),
input_(id, &output_) {
input_(id, &output_)
#else
: input_(id, 0)
#endif
{
}
AudioDeviceAndroidOpenSLES::~AudioDeviceAndroidOpenSLES() {
@ -29,19 +34,35 @@ int32_t AudioDeviceAndroidOpenSLES::ActiveAudioLayer(
}
int32_t AudioDeviceAndroidOpenSLES::Init() {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.Init() | input_.Init();
#else
return input_.Init();
#endif
}
int32_t AudioDeviceAndroidOpenSLES::Terminate() {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.Terminate() | input_.Terminate();
#else
return input_.Terminate();
#endif
}
bool AudioDeviceAndroidOpenSLES::Initialized() const {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.Initialized() && input_.Initialized();
#else
return input_.Initialized();
#endif
}
int16_t AudioDeviceAndroidOpenSLES::PlayoutDevices() {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.PlayoutDevices();
#else
return 0;
#endif
}
int16_t AudioDeviceAndroidOpenSLES::RecordingDevices() {
@ -52,7 +73,11 @@ int32_t AudioDeviceAndroidOpenSLES::PlayoutDeviceName(
uint16_t index,
char name[kAdmMaxDeviceNameSize],
char guid[kAdmMaxGuidSize]) {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.PlayoutDeviceName(index, name, guid);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::RecordingDeviceName(
@ -63,12 +88,20 @@ int32_t AudioDeviceAndroidOpenSLES::RecordingDeviceName(
}
int32_t AudioDeviceAndroidOpenSLES::SetPlayoutDevice(uint16_t index) {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SetPlayoutDevice(index);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::SetPlayoutDevice(
AudioDeviceModule::WindowsDeviceType device) {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SetPlayoutDevice(device);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::SetRecordingDevice(uint16_t index) {
@ -82,15 +115,27 @@ int32_t AudioDeviceAndroidOpenSLES::SetRecordingDevice(
int32_t AudioDeviceAndroidOpenSLES::PlayoutIsAvailable(
bool& available) { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.PlayoutIsAvailable(available);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::InitPlayout() {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.InitPlayout();
#else
return -1;
#endif
}
bool AudioDeviceAndroidOpenSLES::PlayoutIsInitialized() const {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.PlayoutIsInitialized();
#else
return false;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::RecordingIsAvailable(
@ -107,15 +152,27 @@ bool AudioDeviceAndroidOpenSLES::RecordingIsInitialized() const {
}
int32_t AudioDeviceAndroidOpenSLES::StartPlayout() {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.StartPlayout();
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::StopPlayout() {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.StopPlayout();
#else
return -1;
#endif
}
bool AudioDeviceAndroidOpenSLES::Playing() const {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.Playing();
#else
return false;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::StartRecording() {
@ -151,15 +208,27 @@ int32_t AudioDeviceAndroidOpenSLES::WaveOutVolume(
int32_t AudioDeviceAndroidOpenSLES::SpeakerIsAvailable(
bool& available) { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SpeakerIsAvailable(available);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::InitSpeaker() {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.InitSpeaker();
#else
return -1;
#endif
}
bool AudioDeviceAndroidOpenSLES::SpeakerIsInitialized() const {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SpeakerIsInitialized();
#else
return false;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::MicrophoneIsAvailable(
@ -177,31 +246,55 @@ bool AudioDeviceAndroidOpenSLES::MicrophoneIsInitialized() const {
int32_t AudioDeviceAndroidOpenSLES::SpeakerVolumeIsAvailable(
bool& available) { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SpeakerVolumeIsAvailable(available);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::SetSpeakerVolume(uint32_t volume) {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SetSpeakerVolume(volume);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::SpeakerVolume(
uint32_t& volume) const { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SpeakerVolume(volume);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::MaxSpeakerVolume(
uint32_t& maxVolume) const { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.MaxSpeakerVolume(maxVolume);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::MinSpeakerVolume(
uint32_t& minVolume) const { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.MinSpeakerVolume(minVolume);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::SpeakerVolumeStepSize(
uint16_t& stepSize) const { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SpeakerVolumeStepSize(stepSize);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::MicrophoneVolumeIsAvailable(
@ -235,16 +328,28 @@ int32_t AudioDeviceAndroidOpenSLES::MicrophoneVolumeStepSize(
int32_t AudioDeviceAndroidOpenSLES::SpeakerMuteIsAvailable(
bool& available) { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SpeakerMuteIsAvailable(available);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::SetSpeakerMute(bool enable) {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SetSpeakerMute(enable);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::SpeakerMute(
bool& enabled) const { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SpeakerMute(enabled);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::MicrophoneMuteIsAvailable(
@ -277,16 +382,28 @@ int32_t AudioDeviceAndroidOpenSLES::MicrophoneBoost(
int32_t AudioDeviceAndroidOpenSLES::StereoPlayoutIsAvailable(
bool& available) { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.StereoPlayoutIsAvailable(available);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::SetStereoPlayout(bool enable) {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SetStereoPlayout(enable);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::StereoPlayout(
bool& enabled) const { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.StereoPlayout(enabled);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::StereoRecordingIsAvailable(
@ -306,18 +423,30 @@ int32_t AudioDeviceAndroidOpenSLES::StereoRecording(
int32_t AudioDeviceAndroidOpenSLES::SetPlayoutBuffer(
const AudioDeviceModule::BufferType type,
uint16_t sizeMS) {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SetPlayoutBuffer(type, sizeMS);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::PlayoutBuffer(
AudioDeviceModule::BufferType& type,
uint16_t& sizeMS) const { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.PlayoutBuffer(type, sizeMS);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::PlayoutDelay(
uint16_t& delayMS) const { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.PlayoutDelay(delayMS);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::RecordingDelay(
@ -331,11 +460,19 @@ int32_t AudioDeviceAndroidOpenSLES::CPULoad(
}
bool AudioDeviceAndroidOpenSLES::PlayoutWarning() const {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.PlayoutWarning();
#else
return false;
#endif
}
bool AudioDeviceAndroidOpenSLES::PlayoutError() const {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.PlayoutError();
#else
return false;
#endif
}
bool AudioDeviceAndroidOpenSLES::RecordingWarning() const {
@ -347,11 +484,19 @@ bool AudioDeviceAndroidOpenSLES::RecordingError() const {
}
void AudioDeviceAndroidOpenSLES::ClearPlayoutWarning() {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.ClearPlayoutWarning();
#else
return;
#endif
}
void AudioDeviceAndroidOpenSLES::ClearPlayoutError() {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.ClearPlayoutError();
#else
return;
#endif
}
void AudioDeviceAndroidOpenSLES::ClearRecordingWarning() {
@ -364,17 +509,27 @@ void AudioDeviceAndroidOpenSLES::ClearRecordingError() {
void AudioDeviceAndroidOpenSLES::AttachAudioBuffer(
AudioDeviceBuffer* audioBuffer) {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
output_.AttachAudioBuffer(audioBuffer);
#endif
input_.AttachAudioBuffer(audioBuffer);
}
int32_t AudioDeviceAndroidOpenSLES::SetLoudspeakerStatus(bool enable) {
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.SetLoudspeakerStatus(enable);
#else
return -1;
#endif
}
int32_t AudioDeviceAndroidOpenSLES::GetLoudspeakerStatus(
bool& enable) const { // NOLINT
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
return output_.GetLoudspeakerStatus(enable);
#else
return -1;
#endif
}
} // namespace webrtc

View File

@ -155,7 +155,9 @@ class AudioDeviceAndroidOpenSLES : public AudioDeviceGeneric {
virtual int32_t GetLoudspeakerStatus(bool& enable) const;
private:
#ifdef WEBRTC_ANDROID_OPENSLES_OUTPUT
OpenSlesOutput output_;
#endif
OpenSlesInput input_;
};

View File

@ -554,7 +554,8 @@ bool OpenSlesInput::CbThreadImpl() {
while (fifo_->size() > 0 && recording_) {
int8_t* audio = fifo_->Pop();
audio_buffer_->SetRecordedBuffer(audio, buffer_size_samples());
audio_buffer_->SetVQEData(delay_provider_->PlayoutDelayMs(),
audio_buffer_->SetVQEData(delay_provider_ ?
delay_provider_->PlayoutDelayMs() : 0,
recording_delay_, 0);
audio_buffer_->DeliverRecordedData();
}

View File

@ -121,7 +121,7 @@ class OpenSlesInput {
// Keep as few OpenSL buffers as possible to avoid wasting memory. 2 is
// minimum for playout. Keep 2 for recording as well.
kNumOpenSlBuffers = 2,
kNum10MsToBuffer = 4,
kNum10MsToBuffer = 8,
};
int InitSampleRate();

View File

@ -153,7 +153,6 @@
'opensl/opensles_common.h',
'opensl/opensles_input.cc',
'opensl/opensles_input.h',
'opensl/opensles_output.cc',
'opensl/opensles_output.h',
'opensl/single_rw_fifo.cc',
'opensl/single_rw_fifo.h',
@ -168,6 +167,14 @@
'android/audio_device_jni_android.h',
],
}],
['enable_android_opensl_output==1', {
'sources': [
'opensl/opensles_output.cc'
],
'defines': [
'WEBRTC_ANDROID_OPENSLES_OUTPUT',
]},
],
],
}],
['OS=="linux"', {

View File

@ -0,0 +1,23 @@
Backport from upstream.
https://code.google.com/p/double-conversion/source/detail?r=4e24bb31bcc76d6d218f3056b4c24a109d367561
---
mfbt/double-conversion/utils.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/mfbt/double-conversion/utils.h
+++ b/mfbt/double-conversion/utils.h
@@ -58,11 +58,11 @@
defined(__mips__) || \
defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
defined(__SH4__) || defined(__alpha__) || \
defined(_MIPS_ARCH_MIPS32R2) || \
- defined(_AARCH64EL_)
+ defined(__AARCH64EL__)
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
#if defined(_WIN32)
// Windows uses a 64bit wide floating point stack.
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1

View File

@ -20,4 +20,7 @@ patch -p3 < add-mfbt-api-markers.patch
patch -p3 < use-StandardInteger.patch
patch -p3 < use-mozilla-assertions.patch
patch -p3 < use-static_assert.patch
patch -p3 < ToPrecision-exponential.patch
patch -p3 < ToPrecision-exponential.patch
# Merged upstream, part of 2.0.1 version
patch -p3 < fix-aarch64-macro.patch

View File

@ -60,7 +60,7 @@
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
defined(__SH4__) || defined(__alpha__) || \
defined(_MIPS_ARCH_MIPS32R2) || \
defined(_AARCH64EL_)
defined(__AARCH64EL__)
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
#if defined(_WIN32)

View File

@ -2,7 +2,6 @@
# Global options
ac_add_options --enable-debug
ac_add_options --disable-unified-compilation
# Build Fennec
ac_add_options --enable-application=mobile/android

View File

@ -0,0 +1,3 @@
. "$topsrcdir/mobile/android/config/mozconfigs/android/debug"
ac_add_options --disable-unified-compilation

View File

@ -0,0 +1,3 @@
. "$topsrcdir/mobile/android/config/mozconfigs/android/nightly"
ac_add_options --disable-unified-compilation

View File

@ -149,6 +149,13 @@ if CONFIG['OS_ARCH'] == 'NetBSD':
]
if CONFIG['OS_ARCH'] == 'Linux':
if CONFIG['OS_TEST'] == 'aarch64':
SOURCES += [
'xptcinvoke_aarch64.cpp',
'xptcinvoke_asm_aarch64.s',
'xptcstubs_aarch64.cpp',
'xptcstubs_asm_aarch64.s',
]
if CONFIG['OS_TEST'] == 'm68k':
SOURCES += [
'xptcinvoke_linux_m68k.cpp',

View File

@ -0,0 +1,136 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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/. */
/* Platform specific code to invoke XPCOM methods on native objects */
#include "xptcprivate.h"
#if !defined(__aarch64__)
#error "This code is for Linux AArch64 only."
#endif
/* "Procedure Call Standard for the ARM 64-bit Architecture" document, sections
* "5.4 Parameter Passing" and "6.1.2 Procedure Calling" contain all the
* needed information.
*
* http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf
*/
#ifndef __AARCH64EL__
#error "Only little endian compatibility was tested"
#endif
/*
* Allocation of integer function arguments initially to registers r1-r7
* and then to stack. Handling of 'that' argument which goes to register r0
* is handled separately and does not belong here.
*
* 'ireg_args' - pointer to the current position in the buffer,
* corresponding to the register arguments
* 'stack_args' - pointer to the current position in the buffer,
* corresponding to the arguments on stack
* 'end' - pointer to the end of the registers argument
* buffer.
*/
static inline void alloc_word(uint64_t* &ireg_args,
uint64_t* &stack_args,
uint64_t* end,
uint64_t data)
{
if (ireg_args < end) {
*ireg_args = data;
ireg_args++;
} else {
*stack_args = data;
stack_args++;
}
}
static inline void alloc_double(double* &freg_args,
uint64_t* &stack_args,
double* end,
double data)
{
if (freg_args < end) {
*freg_args = data;
freg_args++;
} else {
memcpy(stack_args, &data, sizeof(data));
stack_args++;
}
}
static inline void alloc_float(double* &freg_args,
uint64_t* &stack_args,
double* end,
float data)
{
if (freg_args < end) {
memcpy(freg_args, &data, sizeof(data));
freg_args++;
} else {
memcpy(stack_args, &data, sizeof(data));
stack_args++;
}
}
extern "C" void
invoke_copy_to_stack(uint64_t* stk, uint64_t *end,
uint32_t paramCount, nsXPTCVariant* s)
{
uint64_t *ireg_args = stk;
uint64_t *ireg_end = ireg_args + 8;
double *freg_args = (double *)ireg_end;
double *freg_end = freg_args + 8;
uint64_t *stack_args = (uint64_t *)freg_end;
// leave room for 'that' argument in x0
++ireg_args;
for (uint32_t i = 0; i < paramCount; i++, s++) {
if (s->IsPtrData()) {
alloc_word(ireg_args, stack_args, ireg_end, (uint64_t)s->ptr);
continue;
}
// According to the ABI, integral types that are smaller than 8 bytes
// are to be passed in 8-byte registers or 8-byte stack slots.
switch (s->type) {
case nsXPTType::T_FLOAT:
alloc_float(freg_args, stack_args, freg_end, s->val.f);
break;
case nsXPTType::T_DOUBLE:
alloc_double(freg_args, stack_args, freg_end, s->val.d);
break;
case nsXPTType::T_I8: alloc_word(ireg_args, stk, end, s->val.i8); break;
case nsXPTType::T_I16: alloc_word(ireg_args, stk, end, s->val.i16); break;
case nsXPTType::T_I32: alloc_word(ireg_args, stk, end, s->val.i32); break;
case nsXPTType::T_I64: alloc_word(ireg_args, stk, end, s->val.i64); break;
case nsXPTType::T_U8: alloc_word(ireg_args, stk, end, s->val.u8); break;
case nsXPTType::T_U16: alloc_word(ireg_args, stk, end, s->val.u16); break;
case nsXPTType::T_U32: alloc_word(ireg_args, stk, end, s->val.u32); break;
case nsXPTType::T_U64: alloc_word(ireg_args, stk, end, s->val.u64); break;
case nsXPTType::T_BOOL: alloc_word(ireg_args, stk, end, s->val.b); break;
case nsXPTType::T_CHAR: alloc_word(ireg_args, stk, end, s->val.c); break;
case nsXPTType::T_WCHAR: alloc_word(ireg_args, stk, end, s->val.wc); break;
default:
// all the others are plain pointer types
alloc_word(ireg_args, stack_args, ireg_end,
reinterpret_cast<uint64_t>(s->val.p));
break;
}
}
}
extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
uint32_t paramCount, nsXPTCVariant* params);
EXPORT_XPCOM_API(nsresult)
NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
uint32_t paramCount, nsXPTCVariant* params)
{
return _NS_InvokeByIndex(that, methodIndex, paramCount, params);
}

View File

@ -0,0 +1,67 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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/. */
.section ".text"
.globl _NS_InvokeByIndex
.type _NS_InvokeByIndex,@function
/*
* _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
* uint32_t paramCount, nsXPTCVariant* params)
*/
_NS_InvokeByIndex:
# set up frame
stp x29, x30, [sp,#-32]!
mov x29, sp
stp x19, x20, [sp,#16]
# save methodIndex across function calls
mov w20, w1
# end of stack area passed to invoke_copy_to_stack
mov x1, sp
# assume 8 bytes of stack for each argument with 16-byte alignment
add w19, w2, #1
and w19, w19, #0xfffffffe
sub sp, sp, w19, uxth #3
# temporary place to store args passed in r0-r7,v0-v7
sub sp, sp, #128
# save 'that' on stack
str x0, [sp]
# start of stack area passed to invoke_copy_to_stack
mov x0, sp
bl invoke_copy_to_stack
# load arguments passed in r0-r7
ldp x6, x7, [sp, #48]
ldp x4, x5, [sp, #32]
ldp x2, x3, [sp, #16]
ldp x0, x1, [sp],#64
# load arguments passed in v0-v7
ldp d6, d7, [sp, #48]
ldp d4, d5, [sp, #32]
ldp d2, d3, [sp, #16]
ldp d0, d1, [sp],#64
# call the method
ldr x16, [x0]
add x16, x16, w20, uxth #3
ldr x16, [x16]
blr x16
add sp, sp, w19, uxth #3
ldp x19, x20, [sp,#16]
ldp x29, x30, [sp],#32
ret
.size _NS_InvokeByIndex, . - _NS_InvokeByIndex

View File

@ -0,0 +1,219 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "xptcprivate.h"
#include "xptiprivate.h"
#ifndef __AARCH64EL__
#error "Only little endian compatibility was tested"
#endif
/*
* This is for AArch64 ABI
*
* When we're called, the "gp" registers are stored in gprData and
* the "fp" registers are stored in fprData. Each array has 8 regs
* but first reg in gprData is a placeholder for 'self'.
*/
extern "C" nsresult
PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args,
uint64_t *gprData, double *fprData)
{
#define PARAM_BUFFER_COUNT 16
#define PARAM_GPR_COUNT 8
#define PARAM_FPR_COUNT 8
nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
nsXPTCMiniVariant* dispatchParams = NULL;
const nsXPTMethodInfo* info;
nsresult result = NS_ERROR_FAILURE;
NS_ASSERTION(self,"no self");
self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
NS_ASSERTION(info,"no method info");
uint32_t paramCount = info->GetParamCount();
// setup variant array pointer
if (paramCount > PARAM_BUFFER_COUNT) {
dispatchParams = new nsXPTCMiniVariant[paramCount];
} else {
dispatchParams = paramBuffer;
}
NS_ASSERTION(dispatchParams,"no place for params");
uint64_t* ap = args;
uint32_t next_gpr = 1; // skip first arg which is 'self'
uint32_t next_fpr = 0;
for (uint32_t i = 0; i < paramCount; i++) {
const nsXPTParamInfo& param = info->GetParam(i);
const nsXPTType& type = param.GetType();
nsXPTCMiniVariant* dp = &dispatchParams[i];
if (param.IsOut() || !type.IsArithmetic()) {
if (next_gpr < PARAM_GPR_COUNT) {
dp->val.p = (void*)gprData[next_gpr++];
} else {
dp->val.p = (void*)*ap++;
}
continue;
}
switch (type) {
case nsXPTType::T_I8:
if (next_gpr < PARAM_GPR_COUNT) {
dp->val.i8 = (int8_t)gprData[next_gpr++];
} else {
dp->val.i8 = (int8_t)*ap++;
}
break;
case nsXPTType::T_I16:
if (next_gpr < PARAM_GPR_COUNT) {
dp->val.i16 = (int16_t)gprData[next_gpr++];
} else {
dp->val.i16 = (int16_t)*ap++;
}
break;
case nsXPTType::T_I32:
if (next_gpr < PARAM_GPR_COUNT) {
dp->val.i32 = (int32_t)gprData[next_gpr++];
} else {
dp->val.i32 = (int32_t)*ap++;
}
break;
case nsXPTType::T_I64:
if (next_gpr < PARAM_GPR_COUNT) {
dp->val.i64 = (int64_t)gprData[next_gpr++];
} else {
dp->val.i64 = (int64_t)*ap++;
}
break;
case nsXPTType::T_U8:
if (next_gpr < PARAM_GPR_COUNT) {
dp->val.u8 = (uint8_t)gprData[next_gpr++];
} else {
dp->val.u8 = (uint8_t)*ap++;
}
break;
case nsXPTType::T_U16:
if (next_gpr < PARAM_GPR_COUNT) {
dp->val.u16 = (uint16_t)gprData[next_gpr++];
} else {
dp->val.u16 = (uint16_t)*ap++;
}
break;
case nsXPTType::T_U32:
if (next_gpr < PARAM_GPR_COUNT) {
dp->val.u32 = (uint32_t)gprData[next_gpr++];
} else {
dp->val.u32 = (uint32_t)*ap++;
}
break;
case nsXPTType::T_U64:
if (next_gpr < PARAM_GPR_COUNT) {
dp->val.u64 = (uint64_t)gprData[next_gpr++];
} else {
dp->val.u64 = (uint64_t)*ap++;
}
break;
case nsXPTType::T_FLOAT:
if (next_fpr < PARAM_FPR_COUNT) {
memcpy(&dp->val.f, &fprData[next_fpr++], sizeof(dp->val.f));
} else {
memcpy(&dp->val.f, ap++, sizeof(dp->val.f));
}
break;
case nsXPTType::T_DOUBLE:
if (next_fpr < PARAM_FPR_COUNT) {
memcpy(&dp->val.d, &fprData[next_fpr++], sizeof(dp->val.d));
} else {
memcpy(&dp->val.d, ap++, sizeof(dp->val.d));
}
break;
case nsXPTType::T_BOOL:
if (next_gpr < PARAM_GPR_COUNT) {
dp->val.b = (bool)gprData[next_gpr++];
} else {
dp->val.b = (bool)*ap++;
}
break;
case nsXPTType::T_CHAR:
if (next_gpr < PARAM_GPR_COUNT) {
dp->val.c = (char)gprData[next_gpr++];
} else {
dp->val.c = (char)*ap++;
}
break;
case nsXPTType::T_WCHAR:
if (next_gpr < PARAM_GPR_COUNT) {
dp->val.wc = (wchar_t)gprData[next_gpr++];
} else {
dp->val.wc = (wchar_t)*ap++;
}
break;
default:
NS_ASSERTION(0, "bad type");
break;
}
}
result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
if (dispatchParams != paramBuffer) {
delete [] dispatchParams;
}
return result;
}
// Load w17 with the constant 'n' and branch to SharedStub().
# define STUB_ENTRY(n) \
__asm__ ( \
".section \".text\" \n\t" \
".align 2\n\t" \
".if "#n" < 10 \n\t" \
".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
".hidden _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \
"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
".elseif "#n" < 100 \n\t" \
".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
".hidden _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
".elseif "#n" < 1000 \n\t" \
".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
".hidden _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \
"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
".else \n\t" \
".err \"stub number "#n" >= 1000 not yet supported\"\n" \
".endif \n\t" \
"mov w17,#"#n" \n\t" \
"b SharedStub \n" \
);
#define SENTINEL_ENTRY(n) \
nsresult nsXPTCStubBase::Sentinel##n() \
{ \
NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
return NS_ERROR_NOT_IMPLEMENTED; \
}
#include "xptcstubsdef.inc"

View File

@ -0,0 +1,39 @@
# 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/.
.set NGPREGS,8
.set NFPREGS,8
.section ".text"
.globl SharedStub
.hidden SharedStub
.type SharedStub,@function
SharedStub:
stp x29, x30, [sp,#-16]!
mov x29, sp
sub sp, sp, #8*(NGPREGS+NFPREGS)
stp x0, x1, [sp, #64+(0*8)]
stp x2, x3, [sp, #64+(2*8)]
stp x4, x5, [sp, #64+(4*8)]
stp x6, x7, [sp, #64+(6*8)]
stp d0, d1, [sp, #(0*8)]
stp d2, d3, [sp, #(2*8)]
stp d4, d5, [sp, #(4*8)]
stp d6, d7, [sp, #(6*8)]
# methodIndex passed from stub
mov w1, w17
add x2, sp, #16+(8*(NGPREGS+NFPREGS))
add x3, sp, #8*NFPREGS
add x4, sp, #0
bl PrepareAndDispatch
add sp, sp, #8*(NGPREGS+NFPREGS)
ldp x29, x30, [sp],#16
ret
.size SharedStub, . - SharedStub