mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c
This commit is contained in:
commit
a9f65835bc
@ -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/");
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}"""
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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_;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
|
3174
js/src/jit/mips/MacroAssembler-mips.cpp
Normal file
3174
js/src/jit/mips/MacroAssembler-mips.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1136
js/src/jit/mips/MacroAssembler-mips.h
Normal file
1136
js/src/jit/mips/MacroAssembler-mips.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -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"));
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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"', {
|
||||
|
23
mfbt/double-conversion/fix-aarch64-macro.patch
Normal file
23
mfbt/double-conversion/fix-aarch64-macro.patch
Normal 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
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -0,0 +1,3 @@
|
||||
. "$topsrcdir/mobile/android/config/mozconfigs/android/debug"
|
||||
|
||||
ac_add_options --disable-unified-compilation
|
@ -0,0 +1,3 @@
|
||||
. "$topsrcdir/mobile/android/config/mozconfigs/android/nightly"
|
||||
|
||||
ac_add_options --disable-unified-compilation
|
@ -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',
|
||||
|
136
xpcom/reflect/xptcall/src/md/unix/xptcinvoke_aarch64.cpp
Normal file
136
xpcom/reflect/xptcall/src/md/unix/xptcinvoke_aarch64.cpp
Normal 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);
|
||||
}
|
67
xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_aarch64.s
Normal file
67
xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_aarch64.s
Normal 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
|
||||
|
||||
|
219
xpcom/reflect/xptcall/src/md/unix/xptcstubs_aarch64.cpp
Normal file
219
xpcom/reflect/xptcall/src/md/unix/xptcstubs_aarch64.cpp
Normal 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"
|
39
xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_aarch64.s
Normal file
39
xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_aarch64.s
Normal 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
|
Loading…
Reference in New Issue
Block a user