Merge the last PGO-green inbound changeset to m-c.

This commit is contained in:
Ryan VanderMeulen 2012-11-02 19:45:46 -04:00
Родитель 14ea9890e4 b880ee6c47
Коммит b7ab9ce7e3
229 изменённых файлов: 5990 добавлений и 2182 удалений

Просмотреть файл

@ -190,9 +190,6 @@ pref("app.privacyURL", "http://www.mozilla.com/%LOCALE%/m/privacy.html");
pref("app.creditsURL", "http://www.mozilla.org/credits/");
pref("app.featuresURL", "http://www.mozilla.com/%LOCALE%/b2g/features/");
pref("app.faqURL", "http://www.mozilla.com/%LOCALE%/b2g/faq/");
// Whether we want to report crashes (headless)
//XXX Remove this pref when bug 801932 is fixed
pref("app.reportCrashes", true);
// Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror)
pref("security.alternate_certificate_error_page", "certerror");
@ -239,7 +236,10 @@ pref("ui.dragThresholdY", 25);
// Layers Acceleration
pref("layers.acceleration.disabled", false);
#ifndef XP_WIN
//TODO: turn this on for Windows in bug 808016
pref("layers.offmainthreadcomposition.enabled", true);
#endif
pref("layers.offmainthreadcomposition.animate-opacity", true);
pref("layers.offmainthreadcomposition.animate-transform", true);
pref("layers.async-video.enabled", true);

Просмотреть файл

@ -59,20 +59,13 @@ function identityCall(message) {
sendAsyncMessage(kIdentityControllerDoMethod, message);
}
function identityFinished() {
log("identity finished. closing dialog");
closeIdentityDialog(function notifySuccess() {
// get ready for next call with a reinit
func = null; options = null;
sendAsyncMessage(kIdentityDelegateFinished);
});
}
/*
* Notify the UI to close the dialog and return to the caller application
* To close the dialog, we first tell the gecko SignInToWebsite manager that it
* can clean up. Then we tell the gaia component that we are finished. It is
* necessary to notify gecko first, so that the message can be sent before gaia
* destroys our context.
*/
function closeIdentityDialog(aCallback) {
function closeIdentityDialog() {
let randomId = uuidgen.generateUUID().toString();
let id = kReceivedIdentityAssertion + "-" + randomId;
let browser = Services.wm.getMostRecentWindow("navigator:browser");
@ -94,6 +87,11 @@ function closeIdentityDialog(aCallback) {
}
});
// tell gecko we're done. fire and forget.
func = null; options = null;
sendAsyncMessage(kIdentityDelegateFinished);
// tell gaia to shut us down
browser.shell.sendChromeEvent(detail);
}
@ -111,7 +109,7 @@ function doInternalWatch() {
identityCall(aParams);
if (aParams.method === "ready") {
log("watch finished.");
identityFinished();
closeIdentityDialog();
}
},
JSON.stringify({loggedInUser: options.loggedInUser, origin: options.origin}),
@ -132,7 +130,7 @@ function doInternalRequest() {
log("request -> assertion, so do login");
identityCall({method:'login',assertion:assertion});
}
identityFinished();
closeIdentityDialog();
},
options);
}
@ -145,7 +143,7 @@ function doInternalLogout(aOptions) {
log("logging you out of ", options.origin);
BrowserID.internal.logout(options.origin, function() {
identityCall({method:'logout'});
identityFinished();
closeIdentityDialog();
});
}
}

Просмотреть файл

@ -143,7 +143,7 @@ let Pipe = {
* provide a callback for handling messages.
*
* @param aRpOptions options describing the Relying Party's
* (dicitonary) call, such as origin and loggedInEmail.
* (dictionary) call, such as origin and loggedInUser.
*
* @param aGaiaOptions showUI: boolean
* (dictionary) message: name of the message to emit
@ -289,11 +289,11 @@ let SignInToWebsiteController = {
*/
_makeDoMethodCallback: function SignInToWebsiteController__makeDoMethodCallback(aRpId) {
return function SignInToWebsiteController_methodCallback(aOptions) {
log("doMethod:", aOptions);
let message = aOptions.json;
if (typeof message === 'string') {
message = JSON.parse(message);
}
log("doMethod:", message.method);
switch(message.method) {
case "ready":
IdentityService.doReady(aRpId);

Просмотреть файл

@ -50,7 +50,7 @@ function uuid() {
function mockDoc(aIdentity, aOrigin, aDoFunc) {
let mockedDoc = {};
mockedDoc.id = uuid();
mockedDoc.loggedInEmail = aIdentity;
mockedDoc.loggedInUser = aIdentity;
mockedDoc.origin = aOrigin;
mockedDoc['do'] = aDoFunc;
mockedDoc.doReady = partial(aDoFunc, 'ready');

Просмотреть файл

@ -44,9 +44,6 @@ function checkStyleEditorForSheetAndLine(aStyleSheetIndex, aLine, aCallback) {
function doCheck(aEditor) {
function checkLineAndCallback() {
info("In checkLineAndCallback()");
ok(aEditor.sourceEditor != null, "sourceeditor not null");
ok(aEditor.sourceEditor.getCaretPosition() != null, "position not null");
ok(aEditor.sourceEditor.getCaretPosition().line != null, "line not null");
is(aEditor.sourceEditor.getCaretPosition().line, aLine,
"Correct line is selected");
if (aCallback) {
@ -54,10 +51,7 @@ function checkStyleEditorForSheetAndLine(aStyleSheetIndex, aLine, aCallback) {
}
}
ok(aEditor, "aEditor is defined.");
// Source-editor is already loaded, check the current line of caret.
if (aEditor.sourceEditor) {
function checkForCorrectSheet() {
if (aEditor.styleSheetIndex != SEC.selectedStyleSheetIndex) {
ok(false, "Correct Style Sheet was not selected.");
if (aCallback) {
@ -66,30 +60,28 @@ function checkStyleEditorForSheetAndLine(aStyleSheetIndex, aLine, aCallback) {
return;
}
info("Correct Style Sheet is selected in the editor");
info("Editor is already loaded, check the current line of caret");
executeSoon(checkLineAndCallback);
}
ok(aEditor, "aEditor is defined.");
// Source-editor is already loaded, check the current sheet and line.
if (aEditor.sourceEditor) {
checkForCorrectSheet();
return;
}
info("source editor is not loaded, waiting for it.");
// Wait for source editor to be loaded.
aEditor.addActionListener({
onAttach: function onAttach() {
info("on attach happened");
aEditor.removeActionListener(this);
info("this removed");
executeSoon(function() {
if (aEditor.styleSheetIndex != SEC.selectedStyleSheetIndex) {
ok(false, "Correct Style Sheet was not selected.");
if (aCallback) {
aCallback();
}
return;
}
checkLineAndCallback()
});
}
// Source-editor is not loaded, polling regularly and waiting for it to load
waitForSuccess({
name: "Wait for the source-editor to load",
validatorFn: function()
{
return aEditor.sourceEditor;
},
successFn: checkForCorrectSheet,
failureFn: aCallback,
});
}
@ -138,18 +130,14 @@ let observer = {
.getEditorForWindow(content.window);
ok(styleEditorWin, "Style Editor Window is defined");
waitForFocus(function() {
//styleEditorWin.addEventListener("load", function onStyleEditorWinLoad() {
//styleEditorWin.removeEventListener("load", onStyleEditorWinLoad);
checkStyleEditorForSheetAndLine(0, 7, function() {
checkStyleEditorForSheetAndLine(1, 6, function() {
window.StyleEditor.toggle();
styleEditorWin = null;
finishTest();
});
EventUtils.sendMouseEvent({ type: "click" }, nodes[1]);
checkStyleEditorForSheetAndLine(0, 7, function() {
checkStyleEditorForSheetAndLine(1, 6, function() {
window.StyleEditor.toggle();
styleEditorWin = null;
finishTest();
});
//});
EventUtils.sendMouseEvent({ type: "click" }, nodes[1]);
});
}, styleEditorWin);
});
}

Просмотреть файл

@ -3,6 +3,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import time
import re
import os
import automationutils
import tempfile
@ -23,6 +24,7 @@ class RemoteAutomation(Automation):
# Default our product to fennec
self._product = "fennec"
self.lastTestSeen = "remoteautomation.py"
Automation.__init__(self)
def setDeviceManager(self, deviceManager):
@ -61,11 +63,13 @@ class RemoteAutomation(Automation):
return env
def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsDir):
def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath):
""" Wait for tests to finish (as evidenced by the process exiting),
or for maxTime elapse, in which case kill the process regardless.
"""
# maxTime is used to override the default timeout, we should honor that
status = proc.wait(timeout = maxTime)
print proc.stdout
self.lastTestSeen = proc.getLastTestSeen
if (status == 1 and self._devicemanager.processExist(proc.procName)):
# Then we timed out, make sure Fennec is dead
@ -128,6 +132,7 @@ class RemoteAutomation(Automation):
def __init__(self, dm, cmd, stdout = None, stderr = None, env = None, cwd = None):
self.dm = dm
self.stdoutlen = 0
self.lastTestSeen = "remoteautomation.py"
self.proc = dm.launchProcess(cmd, stdout, cwd, env, True)
if (self.proc is None):
if cmd[0] == 'am':
@ -177,6 +182,9 @@ class RemoteAutomation(Automation):
@property
def stdout(self):
""" Fetch the full remote log file using devicemanager and return just
the new log entries since the last call (as a multi-line string).
"""
if self.dm.fileExists(self.proc):
try:
t = self.dm.pullFile(self.proc)
@ -185,13 +193,22 @@ class RemoteAutomation(Automation):
# function in dmSUT, so an error here is not necessarily
# the end of the world
return ''
tlen = len(t)
retVal = t[self.stdoutlen:]
self.stdoutlen = tlen
return retVal.strip('\n').strip()
newLogContent = t[self.stdoutlen:]
self.stdoutlen = len(t)
# Match the test filepath from the last TEST-START line found in the new
# log content. These lines are in the form:
# 1234 INFO TEST-START | /filepath/we/wish/to/capture.html\n
testStartFilenames = re.findall(r"TEST-START \| ([^\s]*)", newLogContent)
if testStartFilenames:
self.lastTestSeen = testStartFilenames[-1]
return newLogContent.strip('\n').strip()
else:
return ''
@property
def getLastTestSeen(self):
return self.lastTestSeen
def wait(self, timeout = None):
timer = 0
interval = 5
@ -207,6 +224,9 @@ class RemoteAutomation(Automation):
if (timer > timeout):
break
# Flush anything added to stdout during the sleep
print self.stdout
if (timer >= timeout):
return 1
return 0

Просмотреть файл

@ -107,6 +107,7 @@ check-one-remote:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(topsrcdir)/build \
-I$(topsrcdir)/build/mobile \
-I$(topsrcdir)/testing/mozbase/mozdevice/mozdevice \
$(testxpcsrcdir)/remotexpcshelltests.py \
--symbols-path=$(DIST)/crashreporter-symbols \
--build-info-json=$(DEPTH)/mozinfo.json \

Просмотреть файл

@ -49,7 +49,7 @@ class nsDOMDataChannel : public nsDOMEventTargetHelper,
public mozilla::DataChannelListener
{
public:
nsDOMDataChannel(mozilla::DataChannel* aDataChannel)
nsDOMDataChannel(already_AddRefed<mozilla::DataChannel> aDataChannel)
: mDataChannel(aDataChannel)
, mBinaryType(DC_BINARY_TYPE_BLOB)
{}
@ -92,7 +92,7 @@ private:
JSContext *aCx);
// Owning reference
nsAutoPtr<mozilla::DataChannel> mDataChannel;
nsRefPtr<mozilla::DataChannel> mDataChannel;
nsString mOrigin;
enum
{
@ -492,7 +492,7 @@ nsDOMDataChannel::AppReady()
/* static */
nsresult
NS_NewDOMDataChannel(mozilla::DataChannel* aDataChannel,
NS_NewDOMDataChannel(already_AddRefed<mozilla::DataChannel> aDataChannel,
nsPIDOMWindow* aWindow,
nsIDOMDataChannel** aDomDataChannel)
{

Просмотреть файл

@ -10,6 +10,7 @@
// This defines only what's necessary to create nsDOMDataChannels, since this
// gets used with MOZ_INTERNAL_API not set for media/webrtc/signaling/testing
#include "nsCOMPtr.h"
#include "nsIDOMDataChannel.h"
namespace mozilla {
@ -19,7 +20,7 @@ namespace mozilla {
class nsPIDOMWindow;
nsresult
NS_NewDOMDataChannel(mozilla::DataChannel* dataChannel,
NS_NewDOMDataChannel(already_AddRefed<mozilla::DataChannel> dataChannel,
nsPIDOMWindow* aWindow,
nsIDOMDataChannel** domDataChannel);

Просмотреть файл

@ -744,21 +744,21 @@ class nsDOMMemoryFileDataOwnerMemoryReporter
sha1.finish(digest);
nsAutoCString digestString;
for (uint8_t i = 0; i < sizeof(digest); i++) {
for (size_t i = 0; i < sizeof(digest); i++) {
digestString.AppendPrintf("%02x", digest[i]);
}
nsresult rv = aCallback->Callback(
/* process */ NS_LITERAL_CSTRING(""),
nsPrintfCString(
"explicit/dom/memory-file-data/large/file(length=%d, sha1=%s)",
"explicit/dom/memory-file-data/large/file(length=%llu, sha1=%s)",
owner->mLength, digestString.get()),
nsIMemoryReporter::KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES,
size,
nsPrintfCString(
"Memory used to back a memory file of length %d. The file has a "
"sha1 of %s.\n\n"
"Memory used to back a memory file of length %llu bytes. The file "
"has a sha1 of %s.\n\n"
"Note that the allocator may round up a memory file's length -- "
"that is, an N-byte memory file may take up more than N bytes of "
"memory.",

Просмотреть файл

@ -570,6 +570,7 @@ GK_ATOM(mousethrough, "mousethrough")
GK_ATOM(mouseup, "mouseup")
GK_ATOM(mozfullscreenchange, "mozfullscreenchange")
GK_ATOM(mozfullscreenerror, "mozfullscreenerror")
GK_ATOM(mozpasspointerevents, "mozpasspointerevents")
GK_ATOM(mozpointerlockchange, "mozpointerlockchange")
GK_ATOM(mozpointerlockerror, "mozpointerlockerror")
GK_ATOM(moz_opaque, "moz-opaque")

Просмотреть файл

@ -465,6 +465,8 @@ nsXMLHttpRequest::Init(nsIPrincipal* aPrincipal,
nsPIDOMWindow* aOwnerWindow,
nsIURI* aBaseURI)
{
NS_ASSERTION(!aOwnerWindow || aOwnerWindow->IsOuterWindow(),
"Expecting an outer window here!");
NS_ENSURE_ARG_POINTER(aPrincipal);
Construct(aPrincipal,
aOwnerWindow ? aOwnerWindow->GetCurrentInnerWindow() : nullptr,

Просмотреть файл

@ -312,14 +312,16 @@ public:
static bool IsGStreamerSupportedType(const nsACString& aType);
static bool IsH264Type(const nsACString& aType);
static const char gH264Types[3][16];
static char const *const gH264Codecs[7];
#endif
#ifdef MOZ_WIDGET_GONK
static bool IsOmxEnabled();
static bool IsOmxSupportedType(const nsACString& aType);
static const char gOmxTypes[5][16];
static char const *const gH264Codecs[7];
#endif
#if defined(MOZ_GSTREAMER) || defined(MOZ_WIDGET_GONK)
static char const *const gH264Codecs[9];
#endif
#ifdef MOZ_MEDIA_PLUGINS

Просмотреть файл

@ -2134,12 +2134,14 @@ nsHTMLMediaElement::IsWebMType(const nsACString& aType)
#endif
#if defined(MOZ_GSTREAMER) || defined(MOZ_WIDGET_GONK)
char const *const nsHTMLMediaElement::gH264Codecs[7] = {
char const *const nsHTMLMediaElement::gH264Codecs[9] = {
"avc1.42E01E", // H.264 Constrained Baseline Profile Level 3.0
"avc1.42001E", // H.264 Baseline Profile Level 3.0
"avc1.58A01E", // H.264 Extended Profile Level 3.0
"avc1.4D401E", // H.264 Main Profile Level 3.0
"avc1.64001E", // H.264 High Profile Level 3.0
"avc1.64001F", // H.264 High Profile Level 3.1
"mp4v.20.3", // 3GPP
"mp4a.40.2", // AAC-LC
nullptr
};

Просмотреть файл

@ -56,12 +56,13 @@ public:
bool found = false;
for (uint32_t j = 0; j < mTrackMap.Length(); ++j) {
TrackMapEntry* map = &mTrackMap[j];
if (map->mInputPort == mInputs[i] && map->mInputTrack == tracks.get()) {
if (map->mInputPort == mInputs[i] && map->mInputTrackID == tracks->GetID()) {
bool trackFinished;
if (map->mOutputTrack->IsEnded()) {
StreamBuffer::Track* outputTrack = mBuffer.FindTrack(map->mOutputTrackID);
if (!outputTrack || outputTrack->IsEnded()) {
trackFinished = true;
} else {
CopyTrackData(j, aFrom, aTo, &trackFinished);
CopyTrackData(tracks.get(), j, aFrom, aTo, &trackFinished);
}
mappedTracksFinished[j] = trackFinished;
mappedTracksWithMatchingInputTracks[j] = true;
@ -72,7 +73,7 @@ public:
if (!found) {
bool trackFinished = false;
uint32_t mapIndex = AddTrack(mInputs[i], tracks.get(), aFrom);
CopyTrackData(mapIndex, aFrom, aTo, &trackFinished);
CopyTrackData(tracks.get(), mapIndex, aFrom, aTo, &trackFinished);
mappedTracksFinished.AppendElement(trackFinished);
mappedTracksWithMatchingInputTracks.AppendElement(true);
}
@ -101,8 +102,13 @@ protected:
// Only non-ended tracks are allowed to persist in this map.
struct TrackMapEntry {
MediaInputPort* mInputPort;
StreamBuffer::Track* mInputTrack;
StreamBuffer::Track* mOutputTrack;
// We keep track IDs instead of track pointers because
// tracks can be removed without us being notified (e.g.
// when a finished track is forgotten.) When we need a Track*,
// we call StreamBuffer::FindTrack, which will return null if
// the track has been deleted.
TrackID mInputTrackID;
TrackID mOutputTrackID;
nsAutoPtr<MediaSegment> mSegment;
};
@ -137,15 +143,15 @@ protected:
TrackMapEntry* map = mTrackMap.AppendElement();
map->mInputPort = aPort;
map->mInputTrack = aTrack;
map->mOutputTrack = track;
map->mInputTrackID = aTrack->GetID();
map->mOutputTrackID = track->GetID();
map->mSegment = aTrack->GetSegment()->CreateEmptyClone();
return mTrackMap.Length() - 1;
}
void EndTrack(uint32_t aIndex)
{
StreamBuffer::Track* outputTrack = mTrackMap[aIndex].mOutputTrack;
if (outputTrack->IsEnded())
StreamBuffer::Track* outputTrack = mBuffer.FindTrack(mTrackMap[aIndex].mOutputTrackID);
if (!outputTrack || outputTrack->IsEnded())
return;
for (uint32_t j = 0; j < mListeners.Length(); ++j) {
MediaStreamListener* l = mListeners[j];
@ -159,18 +165,18 @@ protected:
}
outputTrack->SetEnded();
}
void CopyTrackData(uint32_t aMapIndex, GraphTime aFrom, GraphTime aTo,
void CopyTrackData(StreamBuffer::Track* aInputTrack,
uint32_t aMapIndex, GraphTime aFrom, GraphTime aTo,
bool* aOutputTrackFinished)
{
TrackMapEntry* map = &mTrackMap[aMapIndex];
StreamBuffer::Track* inputTrack = map->mInputTrack;
StreamBuffer::Track* outputTrack = map->mOutputTrack;
StreamBuffer::Track* outputTrack = mBuffer.FindTrack(map->mOutputTrackID);
MOZ_ASSERT(outputTrack && !outputTrack->IsEnded(), "Can't copy to ended track");
TrackRate rate = outputTrack->GetRate();
MediaSegment* segment = map->mSegment;
MediaStream* source = map->mInputPort->GetSource();
NS_ASSERTION(!outputTrack->IsEnded(), "Can't copy to ended track");
GraphTime next;
*aOutputTrackFinished = false;
for (GraphTime t = aFrom; t < aTo; t = next) {
@ -194,10 +200,10 @@ protected:
StreamTime inputEnd = source->GraphTimeToStreamTime(interval.mEnd);
TrackTicks inputTrackEndPoint = TRACK_TICKS_MAX;
if (inputTrack->IsEnded()) {
TrackTicks inputEndTicks = inputTrack->TimeToTicksRoundDown(inputEnd);
if (inputTrack->GetEnd() <= inputEndTicks) {
inputTrackEndPoint = inputTrack->GetEnd();
if (aInputTrack->IsEnded()) {
TrackTicks inputEndTicks = aInputTrack->TimeToTicksRoundDown(inputEnd);
if (aInputTrack->GetEnd() <= inputEndTicks) {
inputTrackEndPoint = aInputTrack->GetEnd();
*aOutputTrackFinished = true;
}
}
@ -217,7 +223,7 @@ protected:
// We'll take the latest samples we can.
TrackTicks inputEndTicks = TimeToTicksRoundUp(rate, inputEnd);
TrackTicks inputStartTicks = inputEndTicks - ticks;
segment->AppendSlice(*inputTrack->GetSegment(),
segment->AppendSlice(*aInputTrack->GetSegment(),
NS_MIN(inputTrackEndPoint, inputStartTicks),
NS_MIN(inputTrackEndPoint, inputEndTicks));
LOG(PR_LOG_DEBUG, ("TrackUnionStream %p appending %lld ticks of input data to track %d",

Просмотреть файл

@ -13,6 +13,7 @@
#include "AudioBufferSourceNode.h"
#include "AudioBuffer.h"
#include "GainNode.h"
#include "DelayNode.h"
namespace mozilla {
namespace dom {
@ -94,6 +95,13 @@ AudioContext::CreateGain()
return gainNode.forget();
}
already_AddRefed<DelayNode>
AudioContext::CreateDelay(float aMaxDelayTime)
{
nsRefPtr<DelayNode> delayNode = new DelayNode(this, aMaxDelayTime);
return delayNode.forget();
}
}
}

Просмотреть файл

@ -27,6 +27,7 @@ class AudioDestinationNode;
class AudioBufferSourceNode;
class AudioBuffer;
class GainNode;
class DelayNode;
class AudioContext MOZ_FINAL : public nsWrapperCache,
public EnableWebAudioCheck
@ -65,6 +66,9 @@ public:
already_AddRefed<GainNode>
CreateGain();
already_AddRefed<DelayNode>
CreateDelay(float aMaxDelayTime);
private:
nsCOMPtr<nsIDOMWindow> mWindow;
nsRefPtr<AudioDestinationNode> mDestination;

Просмотреть файл

@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "DelayNode.h"
#include "mozilla/dom/DelayNodeBinding.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(DelayNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DelayNode, AudioNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDelay)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DelayNode, AudioNode)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->mDelay, AudioParam, "delay value")
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DelayNode)
NS_INTERFACE_MAP_END_INHERITING(AudioNode)
NS_IMPL_ADDREF_INHERITED(DelayNode, AudioNode)
NS_IMPL_RELEASE_INHERITED(DelayNode, AudioNode)
DelayNode::DelayNode(AudioContext* aContext, float aMaxDelay)
: AudioNode(aContext)
, mDelay(new AudioParam(aContext, 0.0f, 0.0f, aMaxDelay))
{
}
JSObject*
DelayNode::WrapObject(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap)
{
return DelayNodeBinding::Wrap(aCx, aScope, this, aTriedToWrap);
}
}
}

Просмотреть файл

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef DelayNode_h_
#define DelayNode_h_
#include "AudioNode.h"
#include "AudioParam.h"
namespace mozilla {
namespace dom {
class AudioContext;
class DelayNode : public AudioNode
{
public:
DelayNode(AudioContext* aContext, float aMaxDelay);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DelayNode, AudioNode)
virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap);
virtual uint32_t MaxNumberOfInputs() const MOZ_FINAL MOZ_OVERRIDE
{
return 1;
}
virtual uint32_t MaxNumberOfOutputs() const MOZ_FINAL MOZ_OVERRIDE
{
return 1;
}
AudioParam* DelayTime() const
{
return mDelay;
}
private:
nsRefPtr<AudioParam> mDelay;
};
}
}
#endif

Просмотреть файл

@ -22,6 +22,7 @@ CPPSRCS := \
AudioNode.cpp \
AudioParam.cpp \
AudioSourceNode.cpp \
DelayNode.cpp \
EnableWebAudioCheck.cpp \
GainNode.cpp \
$(NULL)
@ -34,6 +35,7 @@ EXPORTS_mozilla/dom := \
AudioNode.h \
AudioParam.h \
AudioSourceNode.h \
DelayNode.h \
GainNode.h \
$(NULL)

Просмотреть файл

@ -14,6 +14,7 @@ MOCHITEST_FILES := \
test_AudioBuffer.html \
test_AudioContext.html \
test_badConnect.html \
test_delayNode.html \
test_gainNode.html \
test_singleSourceDest.html \
$(NULL)

Просмотреть файл

@ -0,0 +1,69 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test DelayNode</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
SpecialPowers.setBoolPref("media.webaudio.enabled", true);
var context = new mozAudioContext();
var buffer = context.createBuffer(1, 2048, 44100);
for (var i = 0; i < 2048; ++i) {
buffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / 44100);
}
var destination = context.destination;
var source = context.createBufferSource();
var delay = context.createDelay();
source.buffer = buffer;
source.connect(delay);
delay.connect(destination);
ok(delay.delayTime, "The audioparam member must exist");
is(delay.delayTime.value, 0, "Correct initial value");
is(delay.delayTime.defaultValue, 0, "Correct default value");
is(delay.delayTime.minValue, 0, "Correct min value");
is(delay.delayTime.maxValue, 1.0, "Correct max value");
delay.delayTime.value = 0.5;
is(delay.delayTime.value, 0.5, "Correct initial value");
is(delay.delayTime.defaultValue, 0, "Correct default value");
is(delay.delayTime.minValue, 0, "Correct min value");
is(delay.delayTime.maxValue, 1.0, "Correct max value");
var delay2 = context.createDelay(2);
is(delay2.delayTime.value, 0, "Correct initial value");
is(delay2.delayTime.defaultValue, 0, "Correct default value");
is(delay2.delayTime.minValue, 0, "Correct min value");
is(delay2.delayTime.maxValue, 2.0, "Correct max value");
delay2.delayTime.value = 0.5;
is(delay2.delayTime.value, 0.5, "Correct initial value");
is(delay2.delayTime.defaultValue, 0, "Correct default value");
is(delay2.delayTime.minValue, 0, "Correct min value");
is(delay2.delayTime.maxValue, 2.0, "Correct max value");
source.start(0);
SimpleTest.executeSoon(function() {
source.stop(0);
source.disconnect();
delay.disconnect();
SpecialPowers.clearUserPref("media.webaudio.enabled");
SimpleTest.finish();
});
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -806,7 +806,10 @@ nsresult nsDefaultURIFixup::KeywordURIFixup(const nsACString & aURIString,
if (((spaceLoc < dotLoc || quoteLoc < dotLoc) &&
(spaceLoc < colonLoc || quoteLoc < colonLoc) &&
(spaceLoc < qMarkLoc || quoteLoc < qMarkLoc)) ||
qMarkLoc == 0)
qMarkLoc == 0 ||
(dotLoc == uint32_t(kNotFound) &&
colonLoc == uint32_t(kNotFound) &&
qMarkLoc == uint32_t(kNotFound) ) )
{
KeywordToURI(aURIString, aURI);
}

Просмотреть файл

@ -3666,7 +3666,7 @@ MaxScriptRunTimePrefChangedCallback(const char *aPrefName, void *aClosure)
PRTime t;
if (time <= 0) {
// Let scripts run for a really, really long time.
t = LL_INIT(0x40000000, 0);
t = 0x40000000LL << 32;
} else {
t = time * PR_USEC_PER_SEC;
}

Просмотреть файл

@ -140,6 +140,11 @@ DOMInterfaces = {
'nativeType': 'nsICSSDeclaration'
},
'DelayNode': [
{
'resultNotAddRefed': [ 'delayTime' ],
}],
'Document': [
{
'nativeType': 'nsIDocument',

Просмотреть файл

@ -1897,6 +1897,14 @@ class IDLValue(IDLObject):
else:
raise WebIDLError("Value %s is out of range for type %s." %
(self.value, type), [location])
elif self.type.isInteger() and type.isFloat():
# Convert an integer literal into float
if -2**24 <= self.value <= 2**24:
floatType = BuiltinTypes[IDLBuiltinType.Types.float]
return IDLValue(self.location, floatType, float(self.value))
else:
raise WebIDLError("Converting value %s to %s will lose precision." %
(self.value, type), [location])
elif self.type.isString() and type.isEnum():
# Just keep our string, but make sure it's a valid value for this enum
if self.value not in type.inner.values():

Просмотреть файл

@ -118,6 +118,19 @@ def WebIDLTest(parser, harness):
[("Float",
[("::TestMethods::doFloats::arg1", "arg1", "Float", False, False)])])
parser = parser.reset()
threw = False
try:
parser.parse("""
interface A {
void foo(optional float bar = 1);
};
""")
results = parser.finish()
except Exception, x:
threw = True
harness.ok(not threw, "Should allow integer to float type corecion")
parser = parser.reset()
threw = False
try:

Просмотреть файл

@ -29,11 +29,9 @@ USING_BLUETOOTH_NAMESPACE
static struct BluedroidFunctions
{
bool initialized;
bool tried_initialization;
BluedroidFunctions() :
initialized(false),
tried_initialization(false)
initialized(false)
{
}
@ -42,17 +40,13 @@ static struct BluedroidFunctions
int (* bt_is_enabled)();
} sBluedroidFunctions;
bool
static bool
EnsureBluetoothInit()
{
if (sBluedroidFunctions.tried_initialization)
{
return sBluedroidFunctions.initialized;
if (sBluedroidFunctions.initialized) {
return true;
}
sBluedroidFunctions.initialized = false;
sBluedroidFunctions.tried_initialization = true;
void* handle = dlopen("libbluedroid.so", RTLD_LAZY);
if (!handle) {
@ -75,29 +69,12 @@ EnsureBluetoothInit()
NS_ERROR("Failed to attach bt_is_enabled function");
return false;
}
sBluedroidFunctions.initialized = true;
return true;
}
int
IsBluetoothEnabled()
{
return sBluedroidFunctions.bt_is_enabled();
}
int
EnableBluetooth()
{
return sBluedroidFunctions.bt_enable();
}
int
DisableBluetooth()
{
return sBluedroidFunctions.bt_disable();
}
nsresult
static nsresult
StartStopGonkBluetooth(bool aShouldEnable)
{
bool result;
@ -111,16 +88,26 @@ StartStopGonkBluetooth(bool aShouldEnable)
}
// return 1 if it's enabled, 0 if it's disabled, and -1 on error
int isEnabled = IsBluetoothEnabled();
int isEnabled = sBluedroidFunctions.bt_is_enabled();
if ((isEnabled == 1 && aShouldEnable) || (isEnabled == 0 && !aShouldEnable)) {
result = true;
} else if (isEnabled < 0) {
result = false;
} else if (aShouldEnable) {
result = (EnableBluetooth() == 0) ? true : false;
return NS_OK;
}
if (aShouldEnable) {
result = (sBluedroidFunctions.bt_enable() == 0) ? true : false;
if (sBluedroidFunctions.bt_is_enabled() < 0) {
// if isEnabled < 0, this means we brought up the firmware, but something
// went wrong with bluetoothd. Post a warning message, but try to proceed
// with firmware unloading if that was requested, so we can retry later.
NS_WARNING("Bluetooth firmware up, but cannot connect to HCI socket! Check bluetoothd and try stopping/starting bluetooth again.");
// Just disable now, return an error.
if (sBluedroidFunctions.bt_disable() != 0) {
NS_WARNING("Problem shutting down bluetooth after error in bringup!");
}
return NS_ERROR_FAILURE;
}
} else {
result = (DisableBluetooth() == 0) ? true : false;
result = (sBluedroidFunctions.bt_disable() == 0) ? true : false;
}
if (!result) {
NS_WARNING("Could not set gonk bluetooth firmware!");

Просмотреть файл

@ -26,6 +26,7 @@ CameraControlImpl::CameraControlImpl(uint32_t aCameraId, nsIThread* aCameraThrea
, mStartRecordingOnErrorCb(nullptr)
, mOnShutterCb(nullptr)
, mOnClosedCb(nullptr)
, mOnRecorderStateChangeCb(nullptr)
{
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
}
@ -221,6 +222,20 @@ CameraControlImpl::Get(nsICameraClosedCallback** aOnClosed)
return NS_OK;
}
nsresult
CameraControlImpl::Set(nsICameraRecorderStateChange* aOnRecorderStateChange)
{
mOnRecorderStateChangeCb = aOnRecorderStateChange;
return NS_OK;
}
nsresult
CameraControlImpl::Get(nsICameraRecorderStateChange** aOnRecorderStateChange)
{
*aOnRecorderStateChange = mOnRecorderStateChangeCb;
return NS_OK;
}
already_AddRefed<RecorderProfileManager>
CameraControlImpl::GetRecorderProfileManager()
{
@ -239,6 +254,7 @@ CameraControlImpl::Shutdown()
mStartRecordingOnErrorCb = nullptr;
mOnShutterCb = nullptr;
mOnClosedCb = nullptr;
mOnRecorderStateChangeCb = nullptr;
}
void
@ -279,6 +295,18 @@ CameraControlImpl::OnClosed()
}
}
void
CameraControlImpl::OnRecorderStateChange(const nsString& aStateMsg, int32_t aStatus, int32_t aTrackNumber)
{
DOM_CAMERA_LOGI("OnRecorderStateChange: '%s'\n", NS_ConvertUTF16toUTF8(aStateMsg).get());
nsCOMPtr<nsIRunnable> onRecorderStateChange = new CameraRecorderStateChange(mOnRecorderStateChangeCb, aStateMsg, aStatus, aTrackNumber, mWindowId);
nsresult rv = NS_DispatchToMainThread(onRecorderStateChange);
if (NS_FAILED(rv)) {
DOM_CAMERA_LOGE("Failed to dispatch onRecorderStateChange event to main thread (%d)\n", rv);
}
}
nsresult
CameraControlImpl::GetPreviewStream(CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError)
{

Просмотреть файл

@ -67,6 +67,8 @@ public:
nsresult Get(nsICameraShutterCallback** aOnShutter);
nsresult Set(nsICameraClosedCallback* aOnClosed);
nsresult Get(nsICameraClosedCallback** aOnClosed);
nsresult Set(nsICameraRecorderStateChange* aOnRecorderStateChange);
nsresult Get(nsICameraRecorderStateChange** aOnRecorderStateChange);
nsresult SetFocusAreas(JSContext* aCx, const JS::Value& aValue)
{
@ -96,6 +98,7 @@ public:
bool ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder);
void OnShutter();
void OnClosed();
void OnRecorderStateChange(const nsString& aStateMsg, int32_t aStatus, int32_t aTrackNumber);
uint64_t GetWindowId()
{
@ -145,6 +148,7 @@ protected:
nsCOMPtr<nsICameraErrorCallback> mStartRecordingOnErrorCb;
nsCOMPtr<nsICameraShutterCallback> mOnShutterCb;
nsCOMPtr<nsICameraClosedCallback> mOnClosedCb;
nsCOMPtr<nsICameraRecorderStateChange> mOnRecorderStateChangeCb;
private:
CameraControlImpl(const CameraControlImpl&) MOZ_DELETE;
@ -607,6 +611,37 @@ public:
nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
};
// Error result runnable
class CameraRecorderStateChange : public nsRunnable
{
public:
CameraRecorderStateChange(nsICameraRecorderStateChange* onStateChange, const nsString& aStateMsg, int32_t aStatus, int32_t aTrackNumber, uint64_t aWindowId)
: mOnStateChangeCb(onStateChange)
, mStateMsg(aStateMsg)
, mStatus(aStatus)
, mTrackNumber(aTrackNumber)
, mWindowId(aWindowId)
{ }
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
if (mOnStateChangeCb && nsDOMCameraManager::IsWindowStillActive(mWindowId)) {
// For now, just pass the state message and swallow mStatus and mTrackNumber
mOnStateChangeCb->HandleStateChange(mStateMsg);
}
return NS_OK;
}
protected:
nsCOMPtr<nsICameraRecorderStateChange> mOnStateChangeCb;
const nsString mStateMsg;
int32_t mStatus;
int32_t mTrackNumber;
uint64_t mWindowId;
};
} // namespace mozilla
#endif // DOM_CAMERA_CAMERACONTROLIMPL_H

Просмотреть файл

@ -229,6 +229,18 @@ nsDOMCameraControl::SetOnClosed(nsICameraClosedCallback* aOnClosed)
return mCameraControl->Set(aOnClosed);
}
/* attribute nsICameraRecorderStateChange onRecorderStateChange; */
NS_IMETHODIMP
nsDOMCameraControl::GetOnRecorderStateChange(nsICameraRecorderStateChange** aOnRecorderStateChange)
{
return mCameraControl->Get(aOnRecorderStateChange);
}
NS_IMETHODIMP
nsDOMCameraControl::SetOnRecorderStateChange(nsICameraRecorderStateChange* aOnRecorderStateChange)
{
return mCameraControl->Set(aOnRecorderStateChange);
}
/* [implicit_jscontext] void startRecording (in jsval aOptions, in nsIDOMDeviceStorage storageArea, in DOMString filename, in nsICameraStartRecordingCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
NS_IMETHODIMP
nsDOMCameraControl::StartRecording(const JS::Value& aOptions, nsIDOMDeviceStorage* storageArea, const nsAString& filename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
@ -237,6 +249,11 @@ nsDOMCameraControl::StartRecording(const JS::Value& aOptions, nsIDOMDeviceStorag
NS_ENSURE_TRUE(storageArea, NS_ERROR_INVALID_ARG);
CameraStartRecordingOptions options;
// Default values, until the dictionary parser can handle them.
options.rotation = 0;
options.maxFileSizeBytes = 0;
options.maxVideoLengthMs = 0;
nsresult rv = options.Init(cx, &aOptions);
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -29,6 +29,7 @@
#include "nsThread.h"
#include <media/MediaProfiles.h>
#include "mozilla/FileUtils.h"
#include <media/mediaplayer.h>
#include "nsDirectoryServiceDefs.h" // for NS_GetSpecialDirectory
#include "nsPrintfCString.h"
#include "DOMCameraManager.h"
@ -741,7 +742,7 @@ nsGonkCameraControl::StartRecordingImpl(StartRecordingTask* aStartRecording)
return NS_ERROR_FAILURE;
}
nsresult rv = SetupRecording(fd);
nsresult rv = SetupRecording(fd, aStartRecording->mOptions.maxFileSizeBytes, aStartRecording->mOptions.maxVideoLengthMs);
NS_ENSURE_SUCCESS(rv, rv);
if (mRecorder->start() != OK) {
@ -914,8 +915,154 @@ nsGonkCameraControl::SetupVideoMode(const nsAString& aProfile)
return NS_OK;
}
class GonkRecorderListener : public IMediaRecorderClient
{
public:
GonkRecorderListener(nsGonkCameraControl* aCameraControl)
: mCameraControl(aCameraControl)
{
DOM_CAMERA_LOGT("%s:%d : this=%p, aCameraControl=%p\n", __func__, __LINE__, this, mCameraControl.get());
}
void notify(int msg, int ext1, int ext2)
{
if (mCameraControl) {
mCameraControl->HandleRecorderEvent(msg, ext1, ext2);
}
}
IBinder* onAsBinder()
{
DOM_CAMERA_LOGE("onAsBinder() called, should NEVER get called!\n");
return nullptr;
}
protected:
~GonkRecorderListener() { }
nsRefPtr<nsGonkCameraControl> mCameraControl;
};
void
nsGonkCameraControl::HandleRecorderEvent(int msg, int ext1, int ext2)
{
/**
* Refer to base/include/media/mediarecorder.h for a complete list
* of error and info message codes. There are duplicate values
* within the status/error code space, as determined by code inspection:
*
* +------- msg
* | +----- ext1
* | | +--- ext2
* V V V
* 1 MEDIA_RECORDER_EVENT_ERROR
* 1 MEDIA_RECORDER_ERROR_UNKNOWN
* [3] ERROR_MALFORMED
* 100 mediaplayer.h::MEDIA_ERROR_SERVER_DIED
* 0 <always zero>
* 2 MEDIA_RECORDER_EVENT_INFO
* 800 MEDIA_RECORDER_INFO_MAX_DURATION_REACHED
* 0 <always zero>
* 801 MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED
* 0 <always zero>
* 1000 MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS[1b]
* [3] UNKNOWN_ERROR, etc.
* 100 MEDIA_ERROR[4]
* 100 mediaplayer.h::MEDIA_ERROR_SERVER_DIED
* 0 <always zero>
* 100 MEDIA_RECORDER_TRACK_EVENT_ERROR
* 100 MEDIA_RECORDER_TRACK_ERROR_GENERAL[1a]
* [3] UNKNOWN_ERROR, etc.
* 200 MEDIA_RECORDER_ERROR_VIDEO_NO_SYNC_FRAME[2]
* ? <unknown>
* 101 MEDIA_RECORDER_TRACK_EVENT_INFO
* 1000 MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS[1a]
* [3] UNKNOWN_ERROR, etc.
* N see mediarecorder.h::media_recorder_info_type[5]
*
* 1. a) High 4 bits are the track number, the next 12 bits are reserved,
* and the final 16 bits are the actual error code (above).
* b) But not in this case.
* 2. Never actually used in AOSP code?
* 3. Specific error codes are from utils/Errors.h and/or
* include/media/stagefright/MediaErrors.h.
* 4. Only in frameworks/base/media/libmedia/mediaplayer.cpp.
* 5. These are mostly informational and we can ignore them; note that
* although the MEDIA_RECORDER_INFO_MAX_DURATION_REACHED and
* MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED values are defined in this
* enum, they are used with different ext1 codes. /o\
*/
int trackNum = -1; // no track
switch (msg) {
// Recorder-related events
case MEDIA_RECORDER_EVENT_INFO:
switch (ext1) {
case MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED:
DOM_CAMERA_LOGI("recorder-event : info: maximum file size reached\n");
OnRecorderStateChange(NS_LITERAL_STRING("FileSizeLimitReached"), ext2, trackNum);
return;
case MEDIA_RECORDER_INFO_MAX_DURATION_REACHED:
DOM_CAMERA_LOGI("recorder-event : info: maximum video duration reached\n");
OnRecorderStateChange(NS_LITERAL_STRING("VideoLengthLimitReached"), ext2, trackNum);
return;
case MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS:
DOM_CAMERA_LOGI("recorder-event : info: track completed\n");
OnRecorderStateChange(NS_LITERAL_STRING("TrackCompleted"), ext2, trackNum);
return;
}
break;
case MEDIA_RECORDER_EVENT_ERROR:
switch (ext1) {
case MEDIA_RECORDER_ERROR_UNKNOWN:
DOM_CAMERA_LOGE("recorder-event : recorder-error: %d (0x%08x)\n", ext2, ext2);
OnRecorderStateChange(NS_LITERAL_STRING("MediaRecorderFailed"), ext2, trackNum);
return;
case MEDIA_ERROR_SERVER_DIED:
DOM_CAMERA_LOGE("recorder-event : recorder-error: server died\n");
OnRecorderStateChange(NS_LITERAL_STRING("MediaServerFailed"), ext2, trackNum);
return;
}
break;
// Track-related events, see note 1(a) above.
case MEDIA_RECORDER_TRACK_EVENT_INFO:
trackNum = (ext1 & 0xF0000000) >> 28;
ext1 &= 0xFFFF;
switch (ext1) {
case MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS:
if (ext2 == OK) {
DOM_CAMERA_LOGI("recorder-event : track-complete: track %d, %d (0x%08x)\n", trackNum, ext2, ext2);
OnRecorderStateChange(NS_LITERAL_STRING("TrackCompleted"), ext2, trackNum);
return;
}
DOM_CAMERA_LOGE("recorder-event : track-error: track %d, %d (0x%08x)\n", trackNum, ext2, ext2);
OnRecorderStateChange(NS_LITERAL_STRING("TrackFailed"), ext2, trackNum);
return;
case MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME:
DOM_CAMERA_LOGI("recorder-event : track-info: progress in time: %d ms\n", ext2);
return;
}
break;
case MEDIA_RECORDER_TRACK_EVENT_ERROR:
trackNum = (ext1 & 0xF0000000) >> 28;
ext1 &= 0xFFFF;
DOM_CAMERA_LOGE("recorder-event : track-error: track %d, %d (0x%08x)\n", trackNum, ext2, ext2);
OnRecorderStateChange(NS_LITERAL_STRING("TrackFailed"), ext2, trackNum);
return;
}
// All unhandled cases wind up here
DOM_CAMERA_LOGW("recorder-event : unhandled: msg=%d, ext1=%d, ext2=%d\n", msg, ext1, ext2);
}
nsresult
nsGonkCameraControl::SetupRecording(int aFd, int aMaxFileSizeBytes, int aMaxVideoLengthMs)
nsGonkCameraControl::SetupRecording(int aFd, int64_t aMaxFileSizeBytes, int64_t aMaxVideoLengthMs)
{
// choosing a size big enough to hold the params
const size_t SIZE = 256;
@ -929,15 +1076,25 @@ nsGonkCameraControl::SetupRecording(int aFd, int aMaxFileSizeBytes, int aMaxVide
CHECK_SETARG(mRecorder->setCameraHandle((int32_t)mHwHandle));
snprintf(buffer, SIZE, "max-duration=%d", aMaxVideoLengthMs);
DOM_CAMERA_LOGI("maxVideoLengthMs=%lld\n", aMaxVideoLengthMs);
if (aMaxVideoLengthMs == 0) {
aMaxVideoLengthMs = -1;
}
snprintf(buffer, SIZE, "max-duration=%lld", aMaxVideoLengthMs);
CHECK_SETARG(mRecorder->setParameters(String8(buffer)));
snprintf(buffer, SIZE, "max-duration=%d", aMaxFileSizeBytes);
DOM_CAMERA_LOGI("maxFileSizeBytes=%lld\n", aMaxFileSizeBytes);
if (aMaxFileSizeBytes == 0) {
aMaxFileSizeBytes = -1;
}
snprintf(buffer, SIZE, "max-filesize=%lld", aMaxFileSizeBytes);
CHECK_SETARG(mRecorder->setParameters(String8(buffer)));
snprintf(buffer, SIZE, "video-param-rotation-angle-degrees=%d", mVideoRotation);
CHECK_SETARG(mRecorder->setParameters(String8(buffer)));
CHECK_SETARG(mRecorder->setListener(new GonkRecorderListener(this)));
// recording API needs file descriptor of output file
CHECK_SETARG(mRecorder->setOutputFile(aFd, 0, 0));
CHECK_SETARG(mRecorder->prepare());

Просмотреть файл

@ -54,11 +54,12 @@ public:
nsresult GetVideoSizes(nsTArray<CameraSize>& aVideoSizes);
nsresult PushParameters();
nsresult SetupRecording(int aFd, int aMaxFileSizeBytes = -1, int aMaxVideoLengthMs = -1);
nsresult SetupRecording(int aFd, int64_t aMaxFileSizeBytes = -1, int64_t aMaxVideoLengthMs = -1);
nsresult SetupVideoMode(const nsAString& aProfile);
void AutoFocusComplete(bool aSuccess);
void TakePictureComplete(uint8_t* aData, uint32_t aLength);
void HandleRecorderEvent(int msg, int ext1, int ext2);
protected:
~nsGonkCameraControl();

Просмотреть файл

@ -42,6 +42,8 @@ public:
virtual nsresult Get(nsICameraShutterCallback** aOnShutter) = 0;
virtual nsresult Set(nsICameraClosedCallback* aOnClosed) = 0;
virtual nsresult Get(nsICameraClosedCallback** aOnClosed) = 0;
virtual nsresult Set(nsICameraRecorderStateChange* aOnRecorderStateChange) = 0;
virtual nsresult Get(nsICameraRecorderStateChange** aOnRecorderStateChange) = 0;
virtual nsresult SetFocusAreas(JSContext* aCx, const JS::Value& aValue) = 0;
virtual nsresult SetMeteringAreas(JSContext* aCx, const JS::Value& aValue) = 0;
virtual nsresult GetVideoSizes(nsTArray<CameraSize>& aVideoSizes) = 0;

Просмотреть файл

@ -195,8 +195,8 @@ dictionary CameraRecorderOptions
dictionary CameraStartRecordingOptions
{
long rotation;
long maxFileSizeBytes;
long maxVideoLengthMs;
long long maxFileSizeBytes;
long long maxVideoLengthMs;
};
[scriptable, function, uuid(0444a687-4bc9-462c-8246-5423f0fe46a4)]
@ -235,6 +235,12 @@ interface nsICameraClosedCallback : nsISupports
void handleEvent();
};
[scriptable, function, uuid(550d675a-257d-4713-8b3d-0da53eba68fc)]
interface nsICameraRecorderStateChange : nsISupports
{
void handleStateChange(in DOMString newState);
};
[scriptable, function, uuid(a302c6c9-3776-4d1d-a395-f4105d47c3d3)]
interface nsICameraErrorCallback : nsISupports
{
@ -245,7 +251,7 @@ interface nsICameraErrorCallback : nsISupports
attributes here affect the preview, any pictures taken, and/or
any video recorded by the camera.
*/
[scriptable, uuid(0f206acd-196b-4bdf-8198-44c1a0cd1998)]
[scriptable, uuid(70f45209-b69b-4937-bbac-57d82600e2af)]
interface nsICameraControl : nsISupports
{
readonly attribute nsICameraCapabilities capabilities;
@ -341,6 +347,11 @@ interface nsICameraControl : nsISupports
recent call to get the camera. */
attribute nsICameraClosedCallback onClosed;
/* the function to call when the recorder changes state, either because
the recording process encountered an error, or because one of the
recording limits (see CameraStartRecordingOptions) was reached. */
attribute nsICameraRecorderStateChange onRecorderStateChange;
/* tell the camera to attempt to focus the image */
void autoFocus(in nsICameraAutoFocusCallback onSuccess, [optional] in nsICameraErrorCallback onError);

Просмотреть файл

@ -87,17 +87,17 @@ IDPAuthenticationContext.prototype = {
},
};
function RPWatchContext(aID, aOrigin, aLoggedInEmail, aTargetMM) {
function RPWatchContext(aID, aOrigin, aLoggedInUser, aTargetMM) {
this._id = aID;
this._origin = aOrigin;
this._loggedInEmail = aLoggedInEmail;
this._loggedInUser = aLoggedInUser;
this._mm = aTargetMM;
}
RPWatchContext.prototype = {
get id() this._id,
get origin() this._origin,
get loggedInEmail() this._loggedInEmail,
get loggedInUser() this._loggedInUser,
doLogin: function RPWatchContext_onlogin(aAssertion) {
log("doLogin: " + this.id);
@ -221,7 +221,7 @@ this.DOMIdentity = {
// Pass an object with the watch members to Identity.jsm so it can call the
// callbacks.
let context = new RPWatchContext(message.id, message.origin,
message.loggedInEmail, targetMM);
message.loggedInUser, targetMM);
IdentityService.RP.watch(context);
},

Просмотреть файл

@ -16,6 +16,7 @@ const MAX_RP_CALLS = 100;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/IdentityUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
@ -78,24 +79,30 @@ nsDOMIdentity.prototype = {
let message = this.DOMIdentityMessage();
// loggedInEmail
message.loggedInEmail = null;
let emailType = typeof(aOptions["loggedInEmail"]);
if (aOptions["loggedInEmail"] && aOptions["loggedInEmail"] !== "undefined") {
// loggedInUser vs loggedInEmail
// https://developer.mozilla.org/en-US/docs/DOM/navigator.id.watch
// This parameter, loggedInUser, was renamed from loggedInEmail in early
// September, 2012. Both names will continue to work for the time being,
// but code should be changed to use loggedInUser instead.
checkRenamed(aOptions, "loggedInEmail", "loggedInUser");
message["loggedInUser"] = aOptions["loggedInUser"];
let emailType = typeof(aOptions["loggedInUser"]);
if (aOptions["loggedInUser"] && aOptions["loggedInUser"] !== "undefined") {
if (emailType !== "string") {
throw new Error("loggedInEmail must be a String or null");
throw new Error("loggedInUser must be a String or null");
}
// TODO: Bug 767610 - check email format.
// See nsHTMLInputElement::IsValidEmailAddress
if (aOptions["loggedInEmail"].indexOf("@") == -1
|| aOptions["loggedInEmail"].length > MAX_STRING_LENGTH) {
throw new Error("loggedInEmail is not valid");
if (aOptions["loggedInUser"].indexOf("@") == -1
|| aOptions["loggedInUser"].length > MAX_STRING_LENGTH) {
throw new Error("loggedInUser is not valid");
}
// Set loggedInEmail in this block that "undefined" doesn't get through.
message.loggedInEmail = aOptions.loggedInEmail;
// Set loggedInUser in this block that "undefined" doesn't get through.
message.loggedInUser = aOptions.loggedInUser;
}
this._log("loggedInEmail: " + message.loggedInEmail);
this._log("loggedInUser: " + message.loggedInUser);
this._rpWatcher = aOptions;
this._identityInternal._mm.sendAsyncMessage("Identity:RP:Watch", message);

Просмотреть файл

@ -599,21 +599,19 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
}
#endif
if (mFrontSurface) {
#ifdef MOZ_X11
if (mFrontSurface &&
mFrontSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
// This is the "old front buffer" we're about to hand back to
// the plugin. We might still have drawing operations
// referencing it.
mFrontSurface->Finish();
#ifdef MOZ_X11
if (mFrontSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
// XSync here to ensure the server has finished operations on the
// surface before the plugin starts scribbling on it again, or
// worse, destroys it.
FinishX(DefaultXDisplay());
}
#endif
// XSync here to ensure the server has finished operations on the
// surface before the plugin starts scribbling on it again, or
// worse, destroys it.
FinishX(DefaultXDisplay());
}
#endif
if (mFrontSurface && gfxSharedImageSurface::IsSharedImage(mFrontSurface))
*prevSurface = static_cast<gfxSharedImageSurface*>(mFrontSurface.get())->GetShmem();

Просмотреть файл

@ -3866,7 +3866,7 @@ let RIL = {
this.sendDOMMessage(message);
}
if (message.messageClass == GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]) {
if (message && message.messageClass == GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]) {
// `MS shall ensure that the message has been to the SMS data field in
// the (U)SIM before sending an ACK to the SC.` ~ 3GPP 23.038 clause 4
return PDU_FCS_RESERVED;

Просмотреть файл

@ -3,6 +3,6 @@ b2g = true
browser = false
qemu = true
; Bug 805539
;[test_geolocation.js]
; gps = true
[test_geolocation.js]

Просмотреть файл

@ -6,7 +6,8 @@ MARIONETTE_TIMEOUT = 10000;
let geolocation = window.navigator.geolocation;
ok(geolocation);
var target = Object();
var sample = [];
var result = [];
var wpid;
/**
@ -14,17 +15,25 @@ var wpid;
*/
SpecialPowers.addPermission("geolocation", true, document);
/**
* Disable wifi geolocation provider
*/
wifiUri = SpecialPowers.getCharPref("geo.wifi.uri");
SpecialPowers.setCharPref("geo.wifi.uri", "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs?action=stop-responding");
/**
* Helper that compares the geolocation against the web API.
*/
function verifyLocation(callback, expectedLocation) {
geolocation.getCurrentPosition(function(position) {
log("Expected location: " + expectedLocation.latitude + " " + expectedLocation.longitude);
log("Current location: " + position.coords.latitude + " " + position.coords.longitude);
is(expectedLocation.latitude, position.coords.latitude);
is(expectedLocation.longitude, position.coords.longitude);
});
window.setTimeout(callback, 0);
function verifyLocation() {
log("Sample:" + sample.join(','));
log("Result:" + result.join(','));
for (i in sample) {
is(sample.pop(), result.pop());
}
window.setTimeout(cleanup, 0);
}
/**
@ -33,71 +42,75 @@ function verifyLocation(callback, expectedLocation) {
function setup() {
log("Providing initial setup: set geographic position watcher.");
wpid = geolocation.watchPosition(function(position) {
log("Position changes has found.");
log("Watch: Target location: " + target.latitude + " " + target.longitude);
log("Watch: Current location: " + position.coords.latitude + " " + position.coords.longitude);
is(target.latitude, position.coords.latitude, "Latitude isn't match!");
is(target.longitude, position.coords.longitude, "Longitude isn't match!");
log("Position changes: (" + position.coords.latitude + "/" + position.coords.longitude + ")");
result.push(""+position.coords.latitude + "/" + position.coords.longitude);
});
target.latitude = 0;
target.longitude = 0;
lat = 0;
lon = 0;
cmd = "geo fix " + target.longitude + " " + target.latitude;
cmd = "geo fix " + lon + " " + lat;
sample.push(lat+"/"+lon);
runEmulatorCmd(cmd, function(result) {
log("Geolocation setting status: " + result);
verifyLocation(movePosition_1, target);
window.setTimeout(movePosition_1, 0);
});
}
function movePosition_1() {
log("Geolocation changes. Move to Position 1.");
target.latitude = 25;
target.longitude = 121.56499833333334;
lat = 25;
lon = 121.56499833333334;
cmd = "geo fix " + target.longitude + " " + target.latitude;
cmd = "geo fix " + lon + " " + lat;
sample.push(lat+"/"+lon);
runEmulatorCmd(cmd, function(result) {
log("Geolocation setting status: " + result);
verifyLocation(movePosition_2, target);
window.setTimeout(movePosition_2, 0);
});
}
function movePosition_2() {
log("Geolocation changes to a negative longitude. Move to Position 2.");
target.latitude = 37.393;
target.longitude = -122.08199833333335;
lat = 37.393;
lon = -122.08199833333335;
cmd = "geo fix " + target.longitude + " " + target.latitude;
cmd = "geo fix " + lon + " " + lat;
sample.push(lat+"/"+lon);
runEmulatorCmd(cmd, function(result) {
log("Geolocation setting status: " + result);
verifyLocation(movePosition_3, target);
window.setTimeout(movePosition_3, 0);
});
}
function movePosition_3() {
log("Geolocation changes with WatchPosition. Move to Position 3.");
target.latitude = -22;
target.longitude = -43;
lat = -22;
lon = -43;
cmd = "geo fix " + target.longitude + " " + target.latitude;
cmd = "geo fix " + lon + " " + lat;
sample.push(lat+"/"+lon);
geolocation.getCurrentPosition(function(position) {
log("getCurrentPosition: Expected location: ("+lat+"/"+lon+"); Current location: (" + position.coords.latitude + "/" + position.coords.longitude + ")");
is(lat, position.coords.latitude);
is(lon, position.coords.longitude);
});
runEmulatorCmd(cmd, function(result) {
log("Geolocation setting status: " + result);
verifyLocation(cleanup, target);
window.setTimeout(verifyLocation, 0);
});
}
function cleanup() {
geolocation.clearWatch(wpid);
SpecialPowers.removePermission("geolocation", document);
SpecialPowers.setCharPref("geo.wifi.uri", wifiUri);
finish();
}

Просмотреть файл

@ -27,6 +27,8 @@ interface mozAudioContext {
[Creator]
GainNode createGain();
[Creator]
DelayNode createDelay(optional float maxDelayTime = 1);
};

Просмотреть файл

@ -0,0 +1,19 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* The origin of this IDL file is
* https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface DelayNode : AudioNode {
readonly attribute AudioParam delayTime;
};

Просмотреть файл

@ -20,6 +20,7 @@ webidl_files = \
CanvasRenderingContext2D.webidl \
ClientRectList.webidl \
CSSStyleDeclaration.webidl \
DelayNode.webidl \
DOMImplementation.webidl \
DOMTokenList.webidl \
DOMSettableTokenList.webidl \

Просмотреть файл

@ -40,14 +40,13 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
// command always succeeds and we do a string/boolean check for the
// expected results).
var WifiManager = (function() {
function getSdkVersionAndDevice() {
function getSdkVersion() {
Cu.import("resource://gre/modules/systemlibs.js");
let sdkVersion = libcutils.property_get("ro.build.version.sdk");
return { sdkVersion: parseInt(sdkVersion, 10),
device: libcutils.property_get("ro.product.device") };
return parseInt(sdkVersion, 10);
}
let { sdkVersion, device } = getSdkVersionAndDevice();
let sdkVersion = getSdkVersion();
var controlWorker = new ChromeWorker(WIFIWORKER_WORKER);
var eventWorker = new ChromeWorker(WIFIWORKER_WORKER);
@ -720,7 +719,7 @@ var WifiManager = (function() {
}
manager.start = function() {
debug("detected SDK version " + sdkVersion + " and device " + device);
debug("detected SDK version " + sdkVersion);
connectToSupplicant(connectCallback);
}
@ -1008,15 +1007,11 @@ var WifiManager = (function() {
});
}
// Driver startup on the otoro takes longer than it takes for us
// Driver startup on certain platforms takes longer than it takes for us
// to return from loadDriver, so wait 2 seconds before starting
// the supplicant to give it a chance to start.
if (device === "otoro") {
timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.init(doStartSupplicant, 2000, Ci.nsITimer.TYPE_ONE_SHOT);
} else {
doStartSupplicant();
}
timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.init(doStartSupplicant, 2000, Ci.nsITimer.TYPE_ONE_SHOT);
});
});
});

Просмотреть файл

@ -154,12 +154,26 @@ public:
NS_ASSERTION(mWorkerPrivate, "Must have a worker here!");
if (!mXHR) {
nsPIDOMWindow* ownerWindow = mWorkerPrivate->GetWindow();
if (ownerWindow) {
ownerWindow = ownerWindow->GetOuterWindow();
if (!ownerWindow) {
NS_ERROR("No outer window?!");
return false;
}
nsPIDOMWindow* innerWindow = ownerWindow->GetCurrentInnerWindow();
if (mWorkerPrivate->GetWindow() != innerWindow) {
NS_WARNING("Window has navigated, cannot create XHR here.");
return false;
}
}
mXHR = new nsXMLHttpRequest();
if (NS_FAILED(mXHR->Init(mWorkerPrivate->GetPrincipal(),
mWorkerPrivate->GetScriptContext(),
mWorkerPrivate->GetWindow(),
mWorkerPrivate->GetBaseURI()))) {
ownerWindow, mWorkerPrivate->GetBaseURI()))) {
mXHR = nullptr;
return false;
}

Просмотреть файл

@ -136,15 +136,8 @@ PathSkia::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
return false;
}
SkRegion pointRect;
pointRect.setRect(int32_t(SkFloatToScalar(transformed.x - 1)),
int32_t(SkFloatToScalar(transformed.y - 1)),
int32_t(SkFloatToScalar(transformed.x + 1)),
int32_t(SkFloatToScalar(transformed.y + 1)));
SkRegion pathRegion;
return pathRegion.setPath(mPath, pointRect);
return mPath.contains(SkFloatToScalar(transformed.x),
SkFloatToScalar(transformed.y));
}
static Rect SkRectToRect(const SkRect& aBounds)

Просмотреть файл

@ -727,6 +727,9 @@ public:
void SetPostScale(float aXScale, float aYScale)
{
if (mPostXScale == aXScale && mPostYScale == aYScale) {
return;
}
mPostXScale = aXScale;
mPostYScale = aYScale;
Mutated();
@ -1232,6 +1235,9 @@ public:
void SetPreScale(float aXScale, float aYScale)
{
if (mPreXScale == aXScale && mPreYScale == aYScale) {
return;
}
mPreXScale = aXScale;
mPreYScale = aYScale;
Mutated();

Просмотреть файл

@ -37,7 +37,7 @@ gfxUserFontSet::GetUserFontsLog()
#define LOG(args) PR_LOG(GetUserFontsLog(), PR_LOG_DEBUG, args)
#define LOG_ENABLED() PR_LOG_TEST(GetUserFontsLog(), PR_LOG_DEBUG)
static uint64_t sFontSetGeneration = LL_INIT(0, 0);
static uint64_t sFontSetGeneration = 0;
// TODO: support for unicode ranges not yet implemented

Просмотреть файл

@ -16,13 +16,6 @@
* We are specializing nsAutoRef class.
*/
template <>
class nsAutoRefTraits<DBusGProxy> : public nsPointerRefTraits<DBusGProxy>
{
public:
static void Release(DBusGProxy* ptr) { g_object_unref(ptr); }
};
template <>
class nsAutoRefTraits<GHashTable> : public nsPointerRefTraits<GHashTable>
{
@ -71,13 +64,17 @@ private:
* Update the currently tracked device.
* @return whether everything went ok.
*/
void UpdateTrackedDevice();
void UpdateTrackedDeviceSync();
/**
* Returns a hash table with the properties of aDevice.
* Note: the caller has to unref the hash table.
*/
GHashTable* GetDeviceProperties(const gchar* aDevice);
GHashTable* GetDevicePropertiesSync(DBusGProxy* aProxy);
void GetDevicePropertiesAsync(DBusGProxy* aProxy);
static void GetDevicePropertiesCallback(DBusGProxy* aProxy,
DBusGProxyCall* aCall,
void* aData);
/**
* Using the device properties (aHashTable), this method updates the member
@ -107,6 +104,9 @@ private:
// The path of the tracked device.
gchar* mTrackedDevice;
// The DBusGProxy for the tracked device.
DBusGProxy* mTrackedDeviceProxy;
double mLevel;
bool mCharging;
double mRemainingTime;
@ -165,6 +165,7 @@ UPowerClient::UPowerClient()
: mDBusConnection(nullptr)
, mUPowerProxy(nullptr)
, mTrackedDevice(nullptr)
, mTrackedDeviceProxy(nullptr)
, mLevel(kDefaultLevel)
, mCharging(kDefaultCharging)
, mRemainingTime(kDefaultRemainingTime)
@ -173,7 +174,7 @@ UPowerClient::UPowerClient()
UPowerClient::~UPowerClient()
{
NS_ASSERTION(!mDBusConnection && !mUPowerProxy && !mTrackedDevice,
NS_ASSERTION(!mDBusConnection && !mUPowerProxy && !mTrackedDevice && !mTrackedDeviceProxy,
"The observers have not been correctly removed! "
"(StopListening should have been called)");
}
@ -206,7 +207,7 @@ UPowerClient::BeginListening()
"/org/freedesktop/UPower",
"org.freedesktop.UPower");
UpdateTrackedDevice();
UpdateTrackedDeviceSync();
/*
* TODO: we should probably listen to DeviceAdded and DeviceRemoved signals.
@ -238,6 +239,11 @@ UPowerClient::StopListening()
g_free(mTrackedDevice);
mTrackedDevice = nullptr;
if (mTrackedDeviceProxy) {
g_object_unref(mTrackedDeviceProxy);
mTrackedDeviceProxy = nullptr;
}
g_object_unref(mUPowerProxy);
mUPowerProxy = nullptr;
@ -251,19 +257,27 @@ UPowerClient::StopListening()
}
void
UPowerClient::UpdateTrackedDevice()
UPowerClient::UpdateTrackedDeviceSync()
{
GType typeGPtrArray = dbus_g_type_get_collection("GPtrArray",
DBUS_TYPE_G_OBJECT_PATH);
GPtrArray* devices = nullptr;
GError* error = nullptr;
// Reset the current tracked device:
g_free(mTrackedDevice);
mTrackedDevice = nullptr;
// Reset the current tracked device proxy:
if (mTrackedDeviceProxy) {
g_object_unref(mTrackedDeviceProxy);
mTrackedDeviceProxy = nullptr;
}
// If that fails, that likely means upower isn't installed.
if (!dbus_g_proxy_call(mUPowerProxy, "EnumerateDevices", &error, G_TYPE_INVALID,
typeGPtrArray, &devices, G_TYPE_INVALID)) {
g_printerr ("Error: %s\n", error->message);
mTrackedDevice = nullptr;
g_error_free(error);
return;
}
@ -274,27 +288,34 @@ UPowerClient::UpdateTrackedDevice()
*/
for (guint i=0; i<devices->len; ++i) {
gchar* devicePath = static_cast<gchar*>(g_ptr_array_index(devices, i));
nsAutoRef<GHashTable> hashTable(GetDeviceProperties(devicePath));
DBusGProxy* proxy = dbus_g_proxy_new_from_proxy(mUPowerProxy,
"org.freedesktop.DBus.Properties",
devicePath);
nsAutoRef<GHashTable> hashTable(GetDevicePropertiesSync(proxy));
if (g_value_get_uint(static_cast<const GValue*>(g_hash_table_lookup(hashTable, "Type"))) == sDeviceTypeBattery) {
UpdateSavedInfo(hashTable);
mTrackedDevice = devicePath;
mTrackedDeviceProxy = proxy;
break;
}
g_object_unref(proxy);
g_free(devicePath);
}
#if GLIB_MAJOR_VERSION >= 2 && GLIB_MINOR_VERSION >= 22
g_ptr_array_unref(devices);
#else
g_ptr_array_free(devices, true);
#endif
g_ptr_array_free(devices, true);
}
/* static */ void
UPowerClient::DeviceChanged(DBusGProxy* aProxy, const gchar* aObjectPath, UPowerClient* aListener)
{
if (!aListener->mTrackedDevice) {
return;
}
#if GLIB_MAJOR_VERSION >= 2 && GLIB_MINOR_VERSION >= 16
if (g_strcmp0(aObjectPath, aListener->mTrackedDevice)) {
#else
@ -303,12 +324,7 @@ UPowerClient::DeviceChanged(DBusGProxy* aProxy, const gchar* aObjectPath, UPower
return;
}
nsAutoRef<GHashTable> hashTable(aListener->GetDeviceProperties(aObjectPath));
aListener->UpdateSavedInfo(hashTable);
hal::NotifyBatteryChange(hal::BatteryInformation(aListener->mLevel,
aListener->mCharging,
aListener->mRemainingTime));
aListener->GetDevicePropertiesAsync(aListener->mTrackedDeviceProxy);
}
/* static */ DBusHandlerResult
@ -325,18 +341,13 @@ UPowerClient::ConnectionSignalFilter(DBusConnection* aConnection,
}
GHashTable*
UPowerClient::GetDeviceProperties(const gchar* aDevice)
UPowerClient::GetDevicePropertiesSync(DBusGProxy* aProxy)
{
nsAutoRef<DBusGProxy> proxy(dbus_g_proxy_new_for_name(mDBusConnection,
"org.freedesktop.UPower",
aDevice,
"org.freedesktop.DBus.Properties"));
GError* error = nullptr;
GHashTable* hashTable = nullptr;
GType typeGHashTable = dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
G_TYPE_VALUE);
if (!dbus_g_proxy_call(proxy, "GetAll", &error, G_TYPE_STRING,
if (!dbus_g_proxy_call(aProxy, "GetAll", &error, G_TYPE_STRING,
"org.freedesktop.UPower.Device", G_TYPE_INVALID,
typeGHashTable, &hashTable, G_TYPE_INVALID)) {
g_printerr("Error: %s\n", error->message);
@ -347,6 +358,35 @@ UPowerClient::GetDeviceProperties(const gchar* aDevice)
return hashTable;
}
/* static */ void
UPowerClient::GetDevicePropertiesCallback(DBusGProxy* aProxy,
DBusGProxyCall* aCall, void* aData)
{
GError* error = nullptr;
GHashTable* hashTable = nullptr;
GType typeGHashTable = dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
G_TYPE_VALUE);
if (!dbus_g_proxy_end_call(aProxy, aCall, &error, typeGHashTable,
&hashTable, G_TYPE_INVALID)) {
g_printerr("Error: %s\n", error->message);
g_error_free(error);
} else {
sInstance->UpdateSavedInfo(hashTable);
hal::NotifyBatteryChange(hal::BatteryInformation(sInstance->mLevel,
sInstance->mCharging,
sInstance->mRemainingTime));
g_hash_table_unref(hashTable);
}
}
void
UPowerClient::GetDevicePropertiesAsync(DBusGProxy* aProxy)
{
dbus_g_proxy_begin_call(aProxy, "GetAll", GetDevicePropertiesCallback, nullptr,
nullptr, G_TYPE_STRING,
"org.freedesktop.UPower.Device", G_TYPE_INVALID);
}
void
UPowerClient::UpdateSavedInfo(GHashTable* aHashTable)
{

Просмотреть файл

@ -55,7 +55,7 @@ bool ObjectWatcher::StartWatching(HANDLE object, Delegate* delegate) {
// Since our job is to just notice when an object is signaled and report the
// result back to this thread, we can just run on a Windows wait thread.
DWORD wait_flags = WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE;
DWORD wait_flags = WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE;
if (!RegisterWaitForSingleObject(&watch->wait_object, object, DoneWaiting,
watch, INFINITE, wait_flags)) {

Просмотреть файл

@ -144,15 +144,6 @@ bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id,
DCHECK(pipe_ == INVALID_HANDLE_VALUE);
const std::wstring pipe_name = PipeName(channel_id);
if (mode == MODE_SERVER) {
SECURITY_ATTRIBUTES security_attributes = {0};
security_attributes.bInheritHandle = FALSE;
security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
if (!win_util::GetLogonSessionOnlyDACL(
reinterpret_cast<SECURITY_DESCRIPTOR**>(
&security_attributes.lpSecurityDescriptor))) {
NOTREACHED();
}
pipe_ = CreateNamedPipeW(pipe_name.c_str(),
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
FILE_FLAG_FIRST_PIPE_INSTANCE,
@ -163,8 +154,7 @@ bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id,
// input buffer size (XXX tune)
Channel::kReadBufferSize,
5000, // timeout in milliseconds (XXX tune)
&security_attributes);
LocalFree(security_attributes.lpSecurityDescriptor);
NULL);
} else {
pipe_ = CreateFileW(pipe_name.c_str(),
GENERIC_READ | GENERIC_WRITE,

Просмотреть файл

@ -146,10 +146,12 @@ struct CompartmentStats
#if JS_HAS_XML_SUPPORT
, gcHeapXML(0)
#endif
, objectSlots(0)
, objectElements(0)
, objectMisc(0)
, objectPrivate(0)
, objectsExtraSlots(0)
, objectsExtraElements(0)
, objectsExtraArgumentsData(0)
, objectsExtraRegExpStatics(0)
, objectsExtraPropertyIteratorData(0)
, objectsExtraPrivate(0)
, stringCharsNonHuge(0)
, shapesExtraTreeTables(0)
, shapesExtraDictTables(0)
@ -186,10 +188,12 @@ struct CompartmentStats
#if JS_HAS_XML_SUPPORT
, gcHeapXML(other.gcHeapXML)
#endif
, objectSlots(other.objectSlots)
, objectElements(other.objectElements)
, objectMisc(other.objectMisc)
, objectPrivate(other.objectPrivate)
, objectsExtraSlots(other.objectsExtraSlots)
, objectsExtraElements(other.objectsExtraElements)
, objectsExtraArgumentsData(other.objectsExtraArgumentsData)
, objectsExtraRegExpStatics(other.objectsExtraRegExpStatics)
, objectsExtraPropertyIteratorData(other.objectsExtraPropertyIteratorData)
, objectsExtraPrivate(other.objectsExtraPrivate)
, stringCharsNonHuge(other.stringCharsNonHuge)
, shapesExtraTreeTables(other.shapesExtraTreeTables)
, shapesExtraDictTables(other.shapesExtraDictTables)
@ -234,10 +238,12 @@ struct CompartmentStats
size_t gcHeapXML;
#endif
size_t objectSlots;
size_t objectElements;
size_t objectMisc;
size_t objectPrivate;
size_t objectsExtraSlots;
size_t objectsExtraElements;
size_t objectsExtraArgumentsData;
size_t objectsExtraRegExpStatics;
size_t objectsExtraPropertyIteratorData;
size_t objectsExtraPrivate;
size_t stringCharsNonHuge;
size_t shapesExtraTreeTables;
size_t shapesExtraDictTables;
@ -280,10 +286,12 @@ struct CompartmentStats
ADD(gcHeapXML);
#endif
ADD(objectSlots);
ADD(objectElements);
ADD(objectMisc);
ADD(objectPrivate);
ADD(objectsExtraSlots);
ADD(objectsExtraElements);
ADD(objectsExtraArgumentsData);
ADD(objectsExtraRegExpStatics);
ADD(objectsExtraPropertyIteratorData);
ADD(objectsExtraPrivate);
ADD(stringCharsNonHuge);
ADD(shapesExtraTreeTables);
ADD(shapesExtraDictTables);

Просмотреть файл

@ -255,7 +255,11 @@ class Vector : private AllocPolicy
/* private accessors */
bool usingInlineStorage() const {
return mBegin == (T *)storage.addr();
return mBegin == inlineStorage();
}
T *inlineStorage() const {
return (T *)storage.addr();
}
T *beginNoCheck() const {
@ -479,6 +483,8 @@ class Vector : private AllocPolicy
* object (which must be heap-allocated) itself.
*/
size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const;
void swap(Vector &other);
};
/* This does the re-entrancy check plus several other sanity checks. */
@ -995,6 +1001,33 @@ Vector<T,N,AP>::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const
return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
}
template <class T, size_t N, class AP>
inline void
Vector<T,N,AP>::swap(Vector &other)
{
// TODO Implement N != 0
JS_STATIC_ASSERT(N == 0);
// This only works when inline storage is always empty.
if (!usingInlineStorage() && other.usingInlineStorage()) {
other.mBegin = mBegin;
mBegin = inlineStorage();
} else if (usingInlineStorage() && !other.usingInlineStorage()) {
mBegin = other.mBegin;
other.mBegin = other.inlineStorage();
} else if (!usingInlineStorage() && !other.usingInlineStorage()) {
Swap(mBegin, other.mBegin);
} else {
// This case is a no-op, since we'd set both to use their inline storage.
}
Swap(mLength, other.mLength);
Swap(mCapacity, other.mCapacity);
#ifdef DEBUG
Swap(mReserved, other.mReserved);
#endif
}
} /* namespace js */
#ifdef _MSC_VER

Просмотреть файл

@ -384,6 +384,7 @@ CPPSRCS += ExecutableAllocator.cpp \
YarrInterpreter.cpp \
YarrPattern.cpp \
YarrSyntaxChecker.cpp \
YarrCanonicalizeUCS2.cpp \
$(NONE)
ifdef ENABLE_METHODJIT_SPEW

Просмотреть файл

@ -291,6 +291,11 @@ namespace JSC {
{
}
int offset() {return m_offset;}
bool isSet() const {
return m_offset != -1;
}
private:
JmpSrc(int offset)
: m_offset(offset)

Просмотреть файл

@ -457,6 +457,10 @@ public:
{
}
bool isSet() const {
return m_offset != -1;
}
private:
JmpSrc(int offset)
: m_offset(offset)

Просмотреть файл

@ -418,6 +418,8 @@ public:
masm->m_assembler.linkJump(m_jmp, label.m_label);
}
bool isSet() const { return m_jmp.isSet(); }
private:
JmpSrc m_jmp;
};

Просмотреть файл

@ -250,6 +250,11 @@ public:
m_assembler.eors_r(dest, dest, ARMRegisters::S1);
}
void load8(BaseIndex address, RegisterID dest)
{
load8ZeroExtend(address, dest);
}
void load8SignExtend(ImplicitAddress address, RegisterID dest)
{
m_assembler.dataTransferN(true, true, 8, dest, address.base, address.offset);
@ -277,6 +282,11 @@ public:
{
load8ZeroExtend(address, dest);
}
void load16Unaligned(BaseIndex address, RegisterID dest)
{
load16(address, dest);
}
void load16SignExtend(ImplicitAddress address, RegisterID dest)
{

Просмотреть файл

@ -206,6 +206,13 @@ public:
m_executablePool = NULL;
}
MacroAssemblerCodePtr code() {
return m_code;
}
size_t size() {
return m_size;
}
MacroAssemblerCodePtr m_code;
ExecutablePool* m_executablePool;
size_t m_size;

Просмотреть файл

@ -414,6 +414,11 @@ public:
m_assembler.movw_rm(src, address.offset, address.base, address.index, address.scale);
}
void load8(BaseIndex address, RegisterID dest)
{
load8ZeroExtend(address, dest);
}
void load8ZeroExtend(BaseIndex address, RegisterID dest)
{
m_assembler.movzbl_mr(address.offset, address.base, address.index, address.scale, dest);
@ -454,6 +459,11 @@ public:
m_assembler.movzwl_mr(address.offset, address.base, dest);
}
void load16Unaligned(BaseIndex address, RegisterID dest)
{
load16(address, dest);
}
DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
{
m_assembler.movl_rm_disp32(src, address.offset, address.base);

Просмотреть файл

@ -378,6 +378,10 @@ public:
return m_offset;
}
bool isSet() const {
return m_offset != -1;
}
private:
int m_offset;
};

Просмотреть файл

@ -1177,6 +1177,11 @@
#define WARN_UNUSED_RETURN
#endif
/* COMPILER(CLANG) - Clang */
#if defined(__clang__)
#define WTF_COMPILER_CLANG 1
#endif
#if !ENABLE_NETSCAPE_PLUGIN_API || (ENABLE_NETSCAPE_PLUGIN_API && ((WTF_OS_UNIX && (WTF_PLATFORM_QT || WTF_PLATFORM_WX)) || WTF_PLATFORM_GTK))
#define ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH 1
#endif

Просмотреть файл

@ -22,6 +22,13 @@ JSObject::asPropertyIterator()
return *static_cast<js::PropertyIteratorObject *>(this);
}
inline const js::PropertyIteratorObject &
JSObject::asPropertyIterator() const
{
JS_ASSERT(isPropertyIterator());
return *static_cast<const js::PropertyIteratorObject *>(this);
}
js::NativeIterator *
js::PropertyIteratorObject::getNativeIterator() const
{

Просмотреть файл

@ -687,6 +687,40 @@ FinalizeCount(JSContext *cx, unsigned argc, jsval *vp)
return true;
}
static JSBool
DumpHeapComplete(JSContext *cx, unsigned argc, jsval *vp)
{
const char *fileName = NULL;
JSAutoByteString fileNameBytes;
if (argc > 0) {
Value v = JS_ARGV(cx, vp)[0];
if (v.isString()) {
JSString *str = v.toString();
if (!fileNameBytes.encode(cx, str))
return false;
fileName = fileNameBytes.ptr();
}
}
FILE *dumpFile;
if (!fileName) {
dumpFile = stdout;
} else {
dumpFile = fopen(fileName, "w");
if (!dumpFile) {
JS_ReportError(cx, "can't open %s", fileName);
return false;
}
}
js::DumpHeapComplete(JS_GetRuntime(cx), dumpFile);
fclose(dumpFile);
JS_SET_RVAL(cx, vp, JSVAL_VOID);
return true;
}
JSBool
MJitChunkLimit(JSContext *cx, unsigned argc, jsval *vp)
{
@ -860,6 +894,10 @@ static JSFunctionSpecWithHelp TestingFunctions[] = {
"isProxy(obj)",
" If true, obj is a proxy of some sort"),
JS_FN_HELP("dumpHeapComplete", DumpHeapComplete, 1, 0,
"dumpHeapComplete([filename])",
" Dump reachable and unreachable objects to a file."),
JS_FN_HELP("mjitChunkLimit", MJitChunkLimit, 1, 0,
"mjitChunkLimit(N)",
" Specify limit on compiled chunk size during mjit compilation."),

Просмотреть файл

@ -17,7 +17,7 @@ def replaceErrorMsgs(source_files, messages_file, output_file):
if len(source_files) == 0:
return
for line in fileinput.input(source_files):
output.write(replaceMessages(line, messages))
output.write(replaceMessages(line if line[-1] == '\n' else line + '\n', messages))
def buildMessagesTable(messages_file):
table = {}
@ -48,4 +48,4 @@ def main():
js2c.JS2C([combined_file, macros_file], [output_file], { 'TYPE': 'CORE', 'COMPRESSION': 'off', 'DEBUG':debug })
if __name__ == "__main__":
main()
main()

Просмотреть файл

@ -107,6 +107,7 @@ check-one-remote:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(topsrcdir)/build \
-I$(topsrcdir)/build/mobile \
-I$(topsrcdir)/testing/mozbase/mozdevice/mozdevice \
$(testxpcsrcdir)/remotexpcshelltests.py \
--symbols-path=$(DIST)/crashreporter-symbols \
--build-info-json=$(DEPTH)/mozinfo.json \

Просмотреть файл

@ -313,8 +313,8 @@ ConvertFrames(JSContext *cx, IonActivation *activation, IonBailoutIterator &it)
return BAILOUT_RETURN_RECOMPILE_CHECK;
case Bailout_BoundsCheck:
return BAILOUT_RETURN_BOUNDS_CHECK;
case Bailout_Invalidate:
return BAILOUT_RETURN_INVALIDATE;
case Bailout_ShapeGuard:
return BAILOUT_RETURN_SHAPE_GUARD;
case Bailout_CachedShapeGuard:
return BAILOUT_RETURN_CACHED_SHAPE_GUARD;
@ -552,7 +552,7 @@ ion::BoundsCheckFailure()
}
uint32
ion::ForceInvalidation()
ion::ShapeGuardFailure()
{
JSContext *cx = GetIonContext()->cx;
JSScript *script = GetBailedJSScript(cx);
@ -560,7 +560,9 @@ ion::ForceInvalidation()
JS_ASSERT(script->hasIonScript());
JS_ASSERT(!script->ion->invalidated());
IonSpew(IonSpew_Invalidate, "Forced invalidation bailout");
script->failedShapeGuard = true;
IonSpew(IonSpew_Invalidate, "Invalidating due to shape guard failure");
return Invalidate(cx, script);
}
@ -574,6 +576,8 @@ ion::CachedShapeGuardFailure()
JS_ASSERT(script->hasIonScript());
JS_ASSERT(!script->ion->invalidated());
script->failedShapeGuard = true;
// Purge JM caches in the script and all inlined script, to avoid baking in
// the same shape guard next time.
for (size_t i = 0; i < script->ion->scriptEntries(); i++)

Просмотреть файл

@ -106,7 +106,7 @@ static const uint32 BAILOUT_RETURN_TYPE_BARRIER = 3;
static const uint32 BAILOUT_RETURN_MONITOR = 4;
static const uint32 BAILOUT_RETURN_RECOMPILE_CHECK = 5;
static const uint32 BAILOUT_RETURN_BOUNDS_CHECK = 6;
static const uint32 BAILOUT_RETURN_INVALIDATE = 7;
static const uint32 BAILOUT_RETURN_SHAPE_GUARD = 7;
static const uint32 BAILOUT_RETURN_OVERRECURSED = 8;
static const uint32 BAILOUT_RETURN_CACHED_SHAPE_GUARD = 9;
@ -222,7 +222,7 @@ uint32 RecompileForInlining();
uint32 BoundsCheckFailure();
uint32 ForceInvalidation();
uint32 ShapeGuardFailure();
uint32 CachedShapeGuardFailure();

Просмотреть файл

@ -1270,7 +1270,7 @@ ion::CanEnterAtBranch(JSContext *cx, HandleScript script, StackFrame *fp, jsbyte
// Attempt compilation. Returns Method_Compiled if already compiled.
JSFunction *fun = fp->isFunctionFrame() ? fp->fun() : NULL;
MethodStatus status = Compile(cx, script, fun, pc, false);
MethodStatus status = Compile(cx, script, fun, pc, fp->isConstructing());
if (status != Method_Compiled) {
if (status == Method_CantCompile)
ForbidCompilation(cx, script);

Просмотреть файл

@ -35,6 +35,7 @@ IonBuilder::IonBuilder(JSContext *cx, TempAllocator *temp, MIRGraph *graph,
oracle(oracle),
inliningDepth(inliningDepth),
failedBoundsCheck_(info->script()->failedBoundsCheck),
failedShapeGuard_(info->script()->failedShapeGuard),
lazyArguments_(NULL)
{
script_.init(info->script());
@ -406,6 +407,9 @@ IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoi
if (callerBuilder->failedBoundsCheck_)
failedBoundsCheck_ = true;
if (callerBuilder->failedShapeGuard_)
failedShapeGuard_ = true;
// Generate single entrance block.
current = newBlock(pc);
if (!current)
@ -4617,10 +4621,8 @@ IonBuilder::jsop_getgname(HandlePropertyName name)
// If we have a property typeset, the isOwnProperty call will trigger recompilation if
// the property is deleted or reconfigured.
if (!propertyTypes && shape->configurable()) {
MGuardShape *guard = MGuardShape::New(global, globalObj->lastProperty(), Bailout_Invalidate);
current->add(guard);
}
if (!propertyTypes && shape->configurable())
global = addShapeGuard(global, globalObj->lastProperty(), Bailout_ShapeGuard);
JS_ASSERT(shape->slot() >= globalObj->numFixedSlots());
@ -4670,10 +4672,8 @@ IonBuilder::jsop_setgname(HandlePropertyName name)
// If we have a property type set, the isOwnProperty call will trigger recompilation
// if the property is deleted or reconfigured. Without TI, we always need a shape guard
// to guard against the property being reconfigured as non-writable.
if (!propertyTypes) {
MGuardShape *guard = MGuardShape::New(global, globalObj->lastProperty(), Bailout_Invalidate);
current->add(guard);
}
if (!propertyTypes)
global = addShapeGuard(global, globalObj->lastProperty(), Bailout_ShapeGuard);
JS_ASSERT(shape->slot() >= globalObj->numFixedSlots());
@ -5436,8 +5436,7 @@ IonBuilder::TestCommonPropFunc(JSContext *cx, types::StackTypeSet *types, Handle
// are no lookup hooks for this property.
MInstruction *wrapper = MConstant::New(ObjectValue(*foundProto));
current->add(wrapper);
MGuardShape *guard = MGuardShape::New(wrapper, foundProto->lastProperty(), Bailout_Invalidate);
current->add(guard);
wrapper = addShapeGuard(wrapper, foundProto->lastProperty(), Bailout_ShapeGuard);
// Now we have to freeze all the property typesets to ensure there isn't a
// lower shadowing getter or setter installed in the future.
@ -5961,8 +5960,7 @@ IonBuilder::getPropTryMonomorphic(bool *emitted, HandleId id, types::StackTypeSe
// the shape is not in dictionary made. We cannot be sure that the shape is
// still a lastProperty, and calling Shape::search() on dictionary mode
// shapes that aren't lastProperty is invalid.
MGuardShape *guard = MGuardShape::New(obj, objShape, Bailout_CachedShapeGuard);
current->add(guard);
obj = addShapeGuard(obj, objShape, Bailout_CachedShapeGuard);
spew("Inlining monomorphic GETPROP");
Shape *shape = objShape->search(cx, id);
@ -6112,8 +6110,7 @@ IonBuilder::jsop_setprop(HandlePropertyName name)
// long as the shape is not in dictionary mode. We cannot be sure
// that the shape is still a lastProperty, and calling Shape::search
// on dictionary mode shapes that aren't lastProperty is invalid.
MGuardShape *guard = MGuardShape::New(obj, objShape, Bailout_CachedShapeGuard);
current->add(guard);
obj = addShapeGuard(obj, objShape, Bailout_CachedShapeGuard);
Shape *shape = objShape->search(cx, NameToId(name));
JS_ASSERT(shape);
@ -6441,3 +6438,16 @@ IonBuilder::addBoundsCheck(MDefinition *index, MDefinition *length)
return check;
}
MInstruction *
IonBuilder::addShapeGuard(MDefinition *obj, const Shape *shape, BailoutKind bailoutKind)
{
MGuardShape *guard = MGuardShape::New(obj, shape, bailoutKind);
current->add(guard);
// If a shape guard failed in the past, don't optimize shape guard.
if (failedShapeGuard_)
guard->setNotMovable();
return guard;
}

Просмотреть файл

@ -280,6 +280,7 @@ class IonBuilder : public MIRGenerator
MDefinition *walkScopeChain(unsigned hops);
MInstruction *addBoundsCheck(MDefinition *index, MDefinition *length);
MInstruction *addShapeGuard(MDefinition *obj, const Shape *shape, BailoutKind bailoutKind);
JSObject *getNewArrayTemplateObject(uint32 count);
@ -473,6 +474,10 @@ class IonBuilder : public MIRGenerator
// an outer script.
bool failedBoundsCheck_;
// True if script->failedShapeGuard is set for the current script or
// an outer script.
bool failedShapeGuard_;
// If this script can use a lazy arguments object, it wil be pre-created
// here.
MInstruction *lazyArguments_;

Просмотреть файл

@ -524,7 +524,7 @@ MacroAssembler::generateBailoutTail(Register scratch)
branch32(Equal, ReturnReg, Imm32(BAILOUT_RETURN_BOUNDS_CHECK), &boundscheck);
branch32(Equal, ReturnReg, Imm32(BAILOUT_RETURN_OVERRECURSED), &overrecursed);
branch32(Equal, ReturnReg, Imm32(BAILOUT_RETURN_INVALIDATE), &invalidate);
branch32(Equal, ReturnReg, Imm32(BAILOUT_RETURN_SHAPE_GUARD), &invalidate);
// Fall-through: cached shape guard failure.
{
@ -539,7 +539,7 @@ MacroAssembler::generateBailoutTail(Register scratch)
bind(&invalidate);
{
setupUnalignedABICall(0, scratch);
callWithABI(JS_FUNC_TO_DATA_PTR(void *, ForceInvalidation));
callWithABI(JS_FUNC_TO_DATA_PTR(void *, ShapeGuardFailure));
branchTest32(Zero, ReturnReg, ReturnReg, &exception);
jump(&interpret);

Просмотреть файл

@ -52,8 +52,8 @@ enum BailoutKind
// A bailout triggered by a bounds-check failure.
Bailout_BoundsCheck,
// Like Bailout_Normal, but invalidate the current IonScript.
Bailout_Invalidate,
// A shape guard based on TI information failed.
Bailout_ShapeGuard,
// A shape guard based on JM ICs failed.
Bailout_CachedShapeGuard

Просмотреть файл

@ -4484,6 +4484,7 @@ class MGuardShape
{
setGuard();
setMovable();
setResultType(MIRType_Object);
}
public:

Просмотреть файл

@ -297,9 +297,15 @@ LIRGeneratorARM::newLTableSwitchV(MTableSwitch *tableswitch)
bool
LIRGeneratorARM::visitGuardShape(MGuardShape *ins)
{
JS_ASSERT(ins->obj()->type() == MIRType_Object);
LDefinition tempObj = temp(LDefinition::OBJECT);
LGuardShape *guard = new LGuardShape(useRegister(ins->obj()), tempObj);
return assignSnapshot(guard, ins->bailoutKind()) && add(guard, ins);
if (!assignSnapshot(guard, ins->bailoutKind()))
return false;
if (!add(guard, ins))
return false;
return redefine(ins, ins->obj());
}
bool

Просмотреть файл

@ -46,8 +46,14 @@ LIRGeneratorX86Shared::visitInterruptCheck(MInterruptCheck *ins)
bool
LIRGeneratorX86Shared::visitGuardShape(MGuardShape *ins)
{
JS_ASSERT(ins->obj()->type() == MIRType_Object);
LGuardShape *guard = new LGuardShape(useRegister(ins->obj()));
return assignSnapshot(guard, ins->bailoutKind()) && add(guard, ins);
if (!assignSnapshot(guard, ins->bailoutKind()))
return false;
if (!add(guard, ins))
return false;
return redefine(ins, ins->obj());
}
bool

Просмотреть файл

@ -52,8 +52,9 @@ BEGIN_TEST(testArrayBuffer_bug720949_steal)
// Steal the contents
void *contents;
CHECK(JS_StealArrayBufferContents(cx, obj, &contents));
CHECK(JS_StealArrayBufferContents(cx, obj, &contents, &data));
CHECK(contents != NULL);
CHECK(data != NULL);
// Check that the original ArrayBuffer is neutered
CHECK_EQUAL(JS_GetArrayBufferByteLength(obj, cx), 0);
@ -111,9 +112,11 @@ BEGIN_TEST(testArrayBuffer_bug720949_viewList)
buffer = JS_NewArrayBuffer(cx, 2000);
js::RootedObject view(cx, JS_NewUint8ArrayWithBuffer(cx, buffer, 0, -1));
void *contents;
CHECK(JS_StealArrayBufferContents(cx, buffer, &contents));
uint8_t *data;
CHECK(JS_StealArrayBufferContents(cx, buffer, &contents, &data));
CHECK(contents != NULL);
JS_free(cx, contents);
CHECK(data != NULL);
JS_free(NULL, contents);
GC(cx);
CHECK(isNeutered(view));
CHECK(isNeutered(buffer));
@ -137,9 +140,11 @@ BEGIN_TEST(testArrayBuffer_bug720949_viewList)
// Neuter
void *contents;
CHECK(JS_StealArrayBufferContents(cx, buffer, &contents));
uint8_t *data;
CHECK(JS_StealArrayBufferContents(cx, buffer, &contents, &data));
CHECK(contents != NULL);
JS_free(cx, contents);
CHECK(data != NULL);
JS_free(NULL, contents);
CHECK(isNeutered(view1));
CHECK(isNeutered(view2));

Просмотреть файл

@ -99,6 +99,7 @@ TestArrayFromBuffer(JSContext *cx)
CHECK_EQUAL(JS_GetTypedArrayLength(array, cx), elts);
CHECK_EQUAL(JS_GetTypedArrayByteOffset(array, cx), 0);
CHECK_EQUAL(JS_GetTypedArrayByteLength(array, cx), nbytes);
CHECK_EQUAL(JS_GetArrayBufferViewBuffer(array, cx), (JSObject*) buffer);
Element *data;
CHECK(data = GetData(array, cx));

Просмотреть файл

@ -3409,6 +3409,7 @@ JS_realloc(JSContext *cx, void *p, size_t nbytes);
/*
* A wrapper for js_free(p) that may delay js_free(p) invocation as a
* performance optimization.
* cx may be NULL.
*/
extern JS_PUBLIC_API(void)
JS_free(JSContext *cx, void *p);
@ -4617,11 +4618,15 @@ JS_NewArrayBufferWithContents(JSContext *cx, void *contents);
/*
* Steal the contents of the given array buffer. The array buffer has its
* length set to 0 and its contents array cleared. The caller takes ownership
* of |contents| and must free it or transfer ownership via
* of |*contents| and must free it or transfer ownership via
* JS_NewArrayBufferWithContents when done using it.
* To free |*contents|, call free().
* A pointer to the buffer's data is returned in |*data|. This pointer can
* be used until |*contents| is freed or has its ownership transferred.
*/
extern JS_PUBLIC_API(JSBool)
JS_StealArrayBufferContents(JSContext *cx, JSObject *obj, void **contents);
JS_StealArrayBufferContents(JSContext *cx, JSObject *obj, void **contents,
uint8_t **data);
/*
* Allocate memory that may be eventually passed to

Просмотреть файл

@ -732,7 +732,8 @@ JSStructuredCloneWriter::writeTransferMap()
return false;
void *content;
if (!JS_StealArrayBufferContents(context(), obj, &content))
uint8_t *data;
if (!JS_StealArrayBufferContents(context(), obj, &content, &data))
return false;
if (!out.writePair(SCTAG_TRANSFER_MAP, 0) || !out.writePtr(content))

Просмотреть файл

@ -561,7 +561,11 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
ionCompartment_->sweep(fop);
#endif
/* JIT code can hold references on RegExpShared, so sweep regexps after clearing code. */
/*
* JIT code increments activeUseCount for any RegExpShared used by jit
* code for the lifetime of the JIT script. Thus, we must perform
* sweeping after clearing jit code.
*/
regExps.sweep(rt);
}

Просмотреть файл

@ -597,32 +597,15 @@ js_DumpObject(JSObject *obj)
#endif
struct DumpingChildInfo {
void *node;
JSGCTraceKind kind;
DumpingChildInfo (void *n, JSGCTraceKind k)
: node(n), kind(k)
{}
};
typedef HashSet<void *, DefaultHasher<void *>, SystemAllocPolicy> PtrSet;
struct JSDumpHeapTracer : public JSTracer {
PtrSet visited;
struct JSDumpHeapTracer : public JSTracer
{
FILE *output;
Vector<DumpingChildInfo, 0, SystemAllocPolicy> nodes;
char buffer[200];
bool rootTracing;
JSDumpHeapTracer(FILE *fp)
: output(fp)
{}
};
static void
DumpHeapVisitChild(JSTracer *trc, void **thingp, JSGCTraceKind kind);
static char
MarkDescriptor(void *thing)
{
@ -634,65 +617,72 @@ MarkDescriptor(void *thing)
}
static void
DumpHeapPushIfNew(JSTracer *trc, void **thingp, JSGCTraceKind kind)
DumpHeapVisitCompartment(JSRuntime *rt, void *data, JSCompartment *comp)
{
JS_ASSERT(trc->callback == DumpHeapPushIfNew ||
trc->callback == DumpHeapVisitChild);
void *thing = *thingp;
JSDumpHeapTracer *dtrc = static_cast<JSDumpHeapTracer *>(trc);
char name[1024];
if (rt->compartmentNameCallback)
(*rt->compartmentNameCallback)(rt, comp, name, sizeof(name));
else
strcpy(name, "<unknown>");
/*
* If we're tracing roots, print root information. Do this even if we've
* already seen thing, for complete root information.
*/
if (dtrc->rootTracing) {
fprintf(dtrc->output, "%p %c %s\n", thing, MarkDescriptor(thing),
JS_GetTraceEdgeName(dtrc, dtrc->buffer, sizeof(dtrc->buffer)));
}
JSDumpHeapTracer *dtrc = static_cast<JSDumpHeapTracer *>(data);
fprintf(dtrc->output, "# compartment %s\n", name);
}
PtrSet::AddPtr ptrEntry = dtrc->visited.lookupForAdd(thing);
if (ptrEntry || !dtrc->visited.add(ptrEntry, thing))
return;
static void
DumpHeapVisitArena(JSRuntime *rt, void *data, gc::Arena *arena,
JSGCTraceKind traceKind, size_t thingSize)
{
JSDumpHeapTracer *dtrc = static_cast<JSDumpHeapTracer *>(data);
fprintf(dtrc->output, "# arena allockind=%u size=%u\n",
unsigned(arena->aheader.getAllocKind()), unsigned(thingSize));
}
dtrc->nodes.append(DumpingChildInfo(thing, kind));
static void
DumpHeapVisitCell(JSRuntime *rt, void *data, void *thing,
JSGCTraceKind traceKind, size_t thingSize)
{
JSDumpHeapTracer *dtrc = static_cast<JSDumpHeapTracer *>(data);
char cellDesc[1024];
JS_GetTraceThingInfo(cellDesc, sizeof(cellDesc), dtrc, thing, traceKind, true);
fprintf(dtrc->output, "%p %c %s\n", thing, MarkDescriptor(thing), cellDesc);
JS_TraceChildren(dtrc, thing, traceKind);
}
static void
DumpHeapVisitChild(JSTracer *trc, void **thingp, JSGCTraceKind kind)
{
JS_ASSERT(trc->callback == DumpHeapVisitChild);
JSDumpHeapTracer *dtrc = static_cast<JSDumpHeapTracer *>(trc);
const char *edgeName = JS_GetTraceEdgeName(dtrc, dtrc->buffer, sizeof(dtrc->buffer));
fprintf(dtrc->output, "> %p %c %s\n", *thingp, MarkDescriptor(*thingp), edgeName);
DumpHeapPushIfNew(dtrc, thingp, kind);
char buffer[1024];
fprintf(dtrc->output, "> %p %c %s\n", *thingp, MarkDescriptor(*thingp),
JS_GetTraceEdgeName(dtrc, buffer, sizeof(buffer)));
}
static void
DumpHeapVisitRoot(JSTracer *trc, void **thingp, JSGCTraceKind kind)
{
JSDumpHeapTracer *dtrc = static_cast<JSDumpHeapTracer *>(trc);
char buffer[1024];
fprintf(dtrc->output, "%p %c %s\n", *thingp, MarkDescriptor(*thingp),
JS_GetTraceEdgeName(dtrc, buffer, sizeof(buffer)));
}
void
js::DumpHeapComplete(JSRuntime *rt, FILE *fp)
{
JSDumpHeapTracer dtrc(fp);
JS_TracerInit(&dtrc, rt, DumpHeapPushIfNew);
if (!dtrc.visited.init(10000))
return;
/* Store and log the root information. */
dtrc.rootTracing = true;
JS_TracerInit(&dtrc, rt, DumpHeapVisitRoot);
TraceRuntime(&dtrc);
fprintf(dtrc.output, "==========\n");
/* Log the graph. */
dtrc.rootTracing = false;
dtrc.callback = DumpHeapVisitChild;
JS_TracerInit(&dtrc, rt, DumpHeapVisitChild);
IterateCompartmentsArenasCells(rt, &dtrc,
DumpHeapVisitCompartment,
DumpHeapVisitArena,
DumpHeapVisitCell);
while (!dtrc.nodes.empty()) {
DumpingChildInfo dci = dtrc.nodes.popCopy();
JS_GetTraceThingInfo(dtrc.buffer, sizeof(dtrc.buffer),
&dtrc, dci.node, dci.kind, JS_TRUE);
fprintf(fp, "%p %c %s\n", dci.node, MarkDescriptor(dci.node), dtrc.buffer);
JS_TraceChildren(&dtrc, dci.node, dci.kind);
}
dtrc.visited.finish();
fflush(dtrc.output);
}

Просмотреть файл

@ -1335,6 +1335,14 @@ JS_GetFloat64ArrayData(JSObject *obj, JSContext *maybecx);
extern JS_FRIEND_API(void *)
JS_GetArrayBufferViewData(JSObject *obj, JSContext *maybecx);
/*
* Return the ArrayBuffer underlying an ArrayBufferView. If the buffer has been
* neutered, this will still return the neutered buffer. |obj| must be an
* object that would return true for JS_IsArrayBufferViewObject().
*/
extern JS_FRIEND_API(JSObject *)
JS_GetArrayBufferViewBuffer(JSObject *obj, JSContext *maybecx);
/*
* Check whether obj supports JS_GetDataView* APIs. Note that this may fail and
* throw an exception if a security wrapper is encountered that denies the

Просмотреть файл

@ -821,6 +821,12 @@ iterator_iteratorObject(JSContext *cx, HandleObject obj, JSBool keysonly)
return obj;
}
size_t
PropertyIteratorObject::sizeOfMisc(JSMallocSizeOfFun mallocSizeOf) const
{
return mallocSizeOf(getPrivate());
}
void
PropertyIteratorObject::trace(JSTracer *trc, RawObject obj)
{

Просмотреть файл

@ -78,6 +78,8 @@ class PropertyIteratorObject : public JSObject
inline NativeIterator *getNativeIterator() const;
inline void setNativeIterator(js::NativeIterator *ni);
size_t sizeOfMisc(JSMallocSizeOfFun mallocSizeOf) const;
private:
static void trace(JSTracer *trc, RawObject obj);
static void finalize(FreeOp *fop, RawObject obj);

Просмотреть файл

@ -155,19 +155,23 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
} else {
cStats->gcHeapObjectsOrdinary += thingSize;
}
size_t slotsSize, elementsSize, miscSize;
obj->sizeOfExcludingThis(rtStats->mallocSizeOf, &slotsSize,
&elementsSize, &miscSize);
cStats->objectSlots += slotsSize;
cStats->objectElements += elementsSize;
cStats->objectMisc += miscSize;
size_t slotsSize, elementsSize, argumentsDataSize, regExpStaticsSize,
propertyIteratorDataSize;
obj->sizeOfExcludingThis(rtStats->mallocSizeOf, &slotsSize, &elementsSize,
&argumentsDataSize, &regExpStaticsSize,
&propertyIteratorDataSize);
cStats->objectsExtraSlots += slotsSize;
cStats->objectsExtraElements += elementsSize;
cStats->objectsExtraArgumentsData += argumentsDataSize;
cStats->objectsExtraRegExpStatics += regExpStaticsSize;
cStats->objectsExtraPropertyIteratorData += propertyIteratorDataSize;
if (ObjectPrivateVisitor *opv = closure->opv) {
js::Class *clazz = js::GetObjectClass(obj);
if (clazz->flags & JSCLASS_HAS_PRIVATE &&
clazz->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS)
{
cStats->objectPrivate += opv->sizeOfIncludingThis(GetObjectPrivate(obj));
cStats->objectsExtraPrivate += opv->sizeOfIncludingThis(GetObjectPrivate(obj));
}
}
break;

Просмотреть файл

@ -368,9 +368,10 @@ struct JSObject : public js::ObjectImpl
inline size_t computedSizeOfThisSlotsElements() const;
inline void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf,
size_t *slotsSize, size_t *elementsSize,
size_t *miscSize) const;
inline void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *slotsSize,
size_t *elementsSize, size_t *argumentsDataSize,
size_t *regExpStaticsSize,
size_t *propertyIteratorDataSize) const;
bool hasIdempotentProtoChain() const;
@ -1020,6 +1021,7 @@ struct JSObject : public js::ObjectImpl
inline js::NormalArgumentsObject &asNormalArguments();
inline js::NumberObject &asNumber();
inline js::PropertyIteratorObject &asPropertyIterator();
inline const js::PropertyIteratorObject &asPropertyIterator() const;
inline js::RegExpObject &asRegExp();
inline js::ScopeObject &asScope();
inline js::SetObject &asSet();

Просмотреть файл

@ -27,6 +27,7 @@
#include "jswrapper.h"
#include "builtin/MapObject.h"
#include "builtin/Iterator-inl.h"
#include "gc/Barrier.h"
#include "gc/Marking.h"
#include "gc/Root.h"
@ -989,9 +990,9 @@ JSObject::computedSizeOfThisSlotsElements() const
}
inline void
JSObject::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf,
size_t *slotsSize, size_t *elementsSize,
size_t *miscSize) const
JSObject::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *slotsSize,
size_t *elementsSize, size_t *argumentsDataSize,
size_t *regExpStaticsSize, size_t *propertyIteratorDataSize) const
{
*slotsSize = 0;
if (hasDynamicSlots()) {
@ -1004,11 +1005,15 @@ JSObject::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf,
}
/* Other things may be measured in the future if DMD indicates it is worthwhile. */
*miscSize = 0;
*argumentsDataSize = 0;
*regExpStaticsSize = 0;
*propertyIteratorDataSize = 0;
if (isArguments()) {
*miscSize += asArguments().sizeOfMisc(mallocSizeOf);
*argumentsDataSize += asArguments().sizeOfMisc(mallocSizeOf);
} else if (isRegExpStatics()) {
*miscSize += js::SizeOfRegExpStaticsData(this, mallocSizeOf);
*regExpStaticsSize += js::SizeOfRegExpStaticsData(this, mallocSizeOf);
} else if (isPropertyIterator()) {
*propertyIteratorDataSize += asPropertyIterator().sizeOfMisc(mallocSizeOf);
}
}

Просмотреть файл

@ -472,6 +472,9 @@ struct JSScript : public js::gc::Cell
#ifdef JS_METHODJIT
bool debugMode:1; /* script was compiled in debug mode */
bool failedBoundsCheck:1; /* script has had hoisted bounds checks fail */
#endif
#ifdef JS_ION
bool failedShapeGuard:1; /* script has had hoisted shape guard fail */
#endif
bool invalidatedIdempotentCache:1; /* idempotent cache has triggered invalidation */
bool isGenerator:1; /* is a generator */

Просмотреть файл

@ -461,13 +461,15 @@ ArrayBufferObject::createDataViewForThis(JSContext *cx, unsigned argc, Value *vp
}
bool
ArrayBufferObject::stealContents(JSContext *cx, JSObject *obj, void **contents)
ArrayBufferObject::stealContents(JSContext *cx, JSObject *obj, void **contents,
uint8_t **data)
{
ArrayBufferObject &buffer = obj->asArrayBuffer();
JSObject *views = *GetViewList(&buffer);
js::ObjectElements *header = js::ObjectElements::fromElements((js::HeapSlot*)buffer.dataPointer());
if (buffer.hasDynamicElements()) {
*contents = header;
*data = buffer.dataPointer();
buffer.setFixedElements();
header = js::ObjectElements::fromElements((js::HeapSlot*)buffer.dataPointer());
@ -482,6 +484,7 @@ ArrayBufferObject::stealContents(JSContext *cx, JSObject *obj, void **contents)
ArrayBufferObject::setElementsHeader(newheader, length);
*contents = newheader;
*data = reinterpret_cast<uint8_t *>(newheader + 1);
}
// Neuter the donor ArrayBuffer and all views of it
@ -3178,7 +3181,7 @@ IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Float64, double)
if (clasp != &TypedArray::classes[TypedArrayTemplate<InternalType>::ArrayTypeID()]) \
return NULL; \
\
*length = obj->getSlot(TypedArray::LENGTH_SLOT).toInt32(); \
*length = TypedArray::length(obj); \
*data = static_cast<ExternalType *>(TypedArray::viewData(obj)); \
\
return obj; \
@ -3675,7 +3678,8 @@ JS_AllocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void **contents,
}
JS_PUBLIC_API(JSBool)
JS_StealArrayBufferContents(JSContext *cx, JSObject *obj, void **contents)
JS_StealArrayBufferContents(JSContext *cx, JSObject *obj, void **contents,
uint8_t **data)
{
if (!(obj = UnwrapObjectChecked(cx, obj)))
return false;
@ -3685,7 +3689,7 @@ JS_StealArrayBufferContents(JSContext *cx, JSObject *obj, void **contents)
return false;
}
if (!ArrayBufferObject::stealContents(cx, obj, contents))
if (!ArrayBufferObject::stealContents(cx, obj, contents, data))
return false;
return true;
@ -3698,7 +3702,7 @@ JS_GetTypedArrayLength(JSObject *obj, JSContext *maybecx)
if (!obj)
return 0;
JS_ASSERT(obj->isTypedArray());
return obj->getSlot(TypedArray::LENGTH_SLOT).toInt32();
return TypedArray::length(obj);
}
JS_FRIEND_API(uint32_t)
@ -3708,7 +3712,7 @@ JS_GetTypedArrayByteOffset(JSObject *obj, JSContext *maybecx)
if (!obj)
return 0;
JS_ASSERT(obj->isTypedArray());
return obj->getSlot(TypedArray::BYTEOFFSET_SLOT).toInt32();
return TypedArray::byteOffset(obj);
}
JS_FRIEND_API(uint32_t)
@ -3718,7 +3722,7 @@ JS_GetTypedArrayByteLength(JSObject *obj, JSContext *maybecx)
if (!obj)
return 0;
JS_ASSERT(obj->isTypedArray());
return obj->getSlot(TypedArray::BYTELENGTH_SLOT).toInt32();
return TypedArray::byteLength(obj);
}
JS_FRIEND_API(JSArrayBufferViewType)
@ -3728,7 +3732,7 @@ JS_GetTypedArrayType(JSObject *obj, JSContext *maybecx)
if (!obj)
return ArrayBufferView::TYPE_MAX;
JS_ASSERT(obj->isTypedArray());
return static_cast<JSArrayBufferViewType>(obj->getSlot(TypedArray::TYPE_SLOT).toInt32());
return static_cast<JSArrayBufferViewType>(TypedArray::type(obj));
}
JS_FRIEND_API(int8_t *)
@ -3738,7 +3742,7 @@ JS_GetInt8ArrayData(JSObject *obj, JSContext *maybecx)
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::TYPE_SLOT).toInt32() == ArrayBufferView::TYPE_INT8);
JS_ASSERT(TypedArray::type(obj) == ArrayBufferView::TYPE_INT8);
return static_cast<int8_t *>(TypedArray::viewData(obj));
}
@ -3749,7 +3753,7 @@ JS_GetUint8ArrayData(JSObject *obj, JSContext *maybecx)
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::TYPE_SLOT).toInt32() == ArrayBufferView::TYPE_UINT8);
JS_ASSERT(TypedArray::type(obj) == ArrayBufferView::TYPE_UINT8);
return static_cast<uint8_t *>(TypedArray::viewData(obj));
}
@ -3760,7 +3764,7 @@ JS_GetUint8ClampedArrayData(JSObject *obj, JSContext *maybecx)
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::TYPE_SLOT).toInt32() == ArrayBufferView::TYPE_UINT8_CLAMPED);
JS_ASSERT(TypedArray::type(obj) == ArrayBufferView::TYPE_UINT8_CLAMPED);
return static_cast<uint8_t *>(TypedArray::viewData(obj));
}
@ -3771,7 +3775,7 @@ JS_GetInt16ArrayData(JSObject *obj, JSContext *maybecx)
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::TYPE_SLOT).toInt32() == ArrayBufferView::TYPE_INT16);
JS_ASSERT(TypedArray::type(obj) == ArrayBufferView::TYPE_INT16);
return static_cast<int16_t *>(TypedArray::viewData(obj));
}
@ -3782,7 +3786,7 @@ JS_GetUint16ArrayData(JSObject *obj, JSContext *maybecx)
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::TYPE_SLOT).toInt32() == ArrayBufferView::TYPE_UINT16);
JS_ASSERT(TypedArray::type(obj) == ArrayBufferView::TYPE_UINT16);
return static_cast<uint16_t *>(TypedArray::viewData(obj));
}
@ -3793,7 +3797,7 @@ JS_GetInt32ArrayData(JSObject *obj, JSContext *maybecx)
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::TYPE_SLOT).toInt32() == ArrayBufferView::TYPE_INT32);
JS_ASSERT(TypedArray::type(obj) == ArrayBufferView::TYPE_INT32);
return static_cast<int32_t *>(TypedArray::viewData(obj));
}
@ -3804,7 +3808,7 @@ JS_GetUint32ArrayData(JSObject *obj, JSContext *maybecx)
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::TYPE_SLOT).toInt32() == ArrayBufferView::TYPE_UINT32);
JS_ASSERT(TypedArray::type(obj) == ArrayBufferView::TYPE_UINT32);
return static_cast<uint32_t *>(TypedArray::viewData(obj));
}
@ -3815,7 +3819,7 @@ JS_GetFloat32ArrayData(JSObject *obj, JSContext *maybecx)
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::TYPE_SLOT).toInt32() == ArrayBufferView::TYPE_FLOAT32);
JS_ASSERT(TypedArray::type(obj) == ArrayBufferView::TYPE_FLOAT32);
return static_cast<float *>(TypedArray::viewData(obj));
}
@ -3826,7 +3830,7 @@ JS_GetFloat64ArrayData(JSObject *obj, JSContext *maybecx)
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(obj->getSlot(TypedArray::TYPE_SLOT).toInt32() == ArrayBufferView::TYPE_FLOAT64);
JS_ASSERT(TypedArray::type(obj) == ArrayBufferView::TYPE_FLOAT64);
return static_cast<double *>(TypedArray::viewData(obj));
}
@ -3880,6 +3884,16 @@ JS_GetArrayBufferViewData(JSObject *obj, JSContext *maybecx)
return obj->isDataView() ? obj->asDataView().dataPointer() : TypedArray::viewData(obj);
}
JS_FRIEND_API(JSObject *)
JS_GetArrayBufferViewBuffer(JSObject *obj, JSContext *maybecx)
{
obj = CheckedUnwrap(maybecx, obj);
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray() || obj->isDataView());
return &obj->getFixedSlot(BufferView::BUFFER_SLOT).toObject();
}
JS_FRIEND_API(uint32_t)
JS_GetArrayBufferViewByteLength(JSObject *obj, JSContext *maybecx)
{

Просмотреть файл

@ -132,7 +132,8 @@ class ArrayBufferObject : public JSObject
static void sweepAll(JSRuntime *rt);
static bool stealContents(JSContext *cx, JSObject *obj, void **contents);
static bool stealContents(JSContext *cx, JSObject *obj, void **contents,
uint8_t **data);
static inline void setElementsHeader(js::ObjectElements *header, uint32_t bytes);

Просмотреть файл

@ -195,7 +195,10 @@ RegExpCode::compile(JSContext *cx, JSLinearString &pattern, unsigned *parenCount
return false;
JSGlobalData globalData(execAlloc);
jitCompile(yarrPattern, &globalData, codeBlock);
jitCompile(yarrPattern,
JSC::Yarr::Char16,
&globalData,
codeBlock);
if (!codeBlock.isFallBack())
return true;
}
@ -218,21 +221,23 @@ RegExpRunStatus
RegExpCode::execute(JSContext *cx, StableCharPtr chars, size_t length, size_t start,
int *output, size_t outputCount)
{
int result;
unsigned result;
#if ENABLE_YARR_JIT
(void) cx; /* Unused. */
if (codeBlock.isFallBack())
result = JSC::Yarr::interpret(byteCode, chars.get(), start, length, output);
else
result = JSC::Yarr::execute(codeBlock, chars.get(), start, length, output);
if (codeBlock.isFallBack()) {
result = JSC::Yarr::interpret(byteCode, chars.get(), length, start,
reinterpret_cast<unsigned *>(output));
} else {
result = codeBlock.execute(chars.get(), start, length, output).start;
}
#else
result = JSC::Yarr::interpret(byteCode, chars.get(), start, length, output);
result = JSC::Yarr::interpret(byteCode, chars.get(), length, start,
reinterpret_cast<unsigned *>(output));
#endif
if (result == -1)
if (result == JSC::Yarr::offsetNoMatch)
return RegExpRunStatus_Success_NotFound;
JS_ASSERT(result >= 0);
return RegExpRunStatus_Success;
}
@ -519,18 +524,19 @@ RegExpShared::execute(JSContext *cx, StableCharPtr chars, size_t length, size_t
/* RegExpCompartment */
RegExpCompartment::RegExpCompartment(JSRuntime *rt)
: map_(rt)
: map_(rt), inUse_(rt)
{}
RegExpCompartment::~RegExpCompartment()
{
map_.empty();
JS_ASSERT(map_.empty());
JS_ASSERT(inUse_.empty());
}
bool
RegExpCompartment::init(JSContext *cx)
{
if (!map_.init()) {
if (!map_.init() || !inUse_.init()) {
js_ReportOutOfMemory(cx);
return false;
}
@ -538,12 +544,19 @@ RegExpCompartment::init(JSContext *cx)
return true;
}
/* See the comment on RegExpShared lifetime in RegExpObject.h. */
void
RegExpCompartment::sweep(JSRuntime *rt)
{
for (Map::Enum e(map_); !e.empty(); e.popFront()) {
/* See the comment on RegExpShared lifetime in RegExpObject.h. */
RegExpShared *shared = e.front().value;
#ifdef DEBUG
for (Map::Range r = map_.all(); !r.empty(); r.popFront())
JS_ASSERT(inUse_.has(r.front().value));
#endif
map_.clear();
for (PendingSet::Enum e(inUse_); !e.empty(); e.popFront()) {
RegExpShared *shared = e.front();
if (shared->activeUseCount == 0 && shared->gcNumberWhenUsed < rt->gcStartNumber) {
js_delete(shared);
e.removeFront();
@ -575,6 +588,12 @@ RegExpCompartment::get(JSContext *cx, JSAtom *keyAtom, JSAtom *source, RegExpFla
return false;
}
if (!inUse_.put(shared)) {
map_.remove(key);
js_ReportOutOfMemory(cx);
return false;
}
/*
* Since 'error' deletes 'shared', only guard 'shared' on success. This is
* safe since 'shared' cannot be deleted by GC until after the call to

Просмотреть файл

@ -140,9 +140,9 @@ class RegExpCode
/*
* A RegExpShared is the compiled representation of a regexp. A RegExpShared is
* pointed to by potentially multiple RegExpObjects. Additionally, C++ code may
* have pointers to RegExpShareds on the stack. The RegExpShareds are tracked in
* a RegExpCompartment hashtable, and most are destroyed on every GC.
* potentially pointed to by multiple RegExpObjects. Additionally, C++ code may
* have pointers to RegExpShareds on the stack. The RegExpShareds are kept in a
* cache so that they can be reused when compiling the same regex string.
*
* During a GC, the trace hook for RegExpObject clears any pointers to
* RegExpShareds so that there will be no dangling pointers when they are
@ -160,6 +160,13 @@ class RegExpCode
*
* The activeUseCount and gcNumberWhenUsed fields are used to track these
* conditions.
*
* There are two tables used to track RegExpShareds. map_ implements the cache
* and is cleared on every GC. inUse_ logically owns all RegExpShareds in the
* compartment and attempts to delete all RegExpShareds that aren't kept alive
* by the above conditions on every GC sweep phase. It is necessary to use two
* separate tables since map_ *must* be fully cleared on each GC since the Key
* points to a JSAtom that can become garbage.
*/
class RegExpShared
{
@ -251,9 +258,21 @@ class RegExpCompartment
}
};
/*
* Cache to reuse RegExpShareds with the same source/flags/etc. The cache
* is entirely cleared on each GC.
*/
typedef HashMap<Key, RegExpShared *, Key, RuntimeAllocPolicy> Map;
Map map_;
/*
* The set of all RegExpShareds in the compartment. On every GC, every
* RegExpShared that is not actively being used is deleted and removed from
* the set.
*/
typedef HashSet<RegExpShared *, DefaultHasher<RegExpShared*>, RuntimeAllocPolicy> PendingSet;
PendingSet inUse_;
bool get(JSContext *cx, JSAtom *key, JSAtom *source, RegExpFlag flags, Type type,
RegExpGuard *g);

Просмотреть файл

@ -0,0 +1,714 @@
/* vim: set ts=4 sw=4 tw=99 et:
*
* Copyright (C) 2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CheckedArithmetic_h
#define CheckedArithmetic_h
#include "assembler/wtf/Assertions.h"
#include "TypeTraits.h"
#include <limits>
#include <stdint.h>
#ifdef _MSC_VER
# undef min
# undef max
#endif
/* Checked<T>
*
* This class provides a mechanism to perform overflow-safe integer arithmetic
* without having to manually ensure that you have all the required bounds checks
* directly in your code.
*
* There are two modes of operation:
* - The default is Checked<T, CrashOnOverflow>, and crashes at the point
* and overflow has occurred.
* - The alternative is Checked<T, RecordOverflow>, which uses an additional
* byte of storage to track whether an overflow has occurred, subsequent
* unchecked operations will crash if an overflow has occured
*
* It is possible to provide a custom overflow handler, in which case you need
* to support these functions:
* - void overflowed();
* This function is called when an operation has produced an overflow.
* - bool hasOverflowed();
* This function must return true if overflowed() has been called on an
* instance and false if it has not.
* - void clearOverflow();
* Used to reset overflow tracking when a value is being overwritten with
* a new value.
*
* Checked<T> works for all integer types, with the following caveats:
* - Mixing signedness of operands is only supported for types narrower than
* 64bits.
* - It does have a performance impact, so tight loops may want to be careful
* when using it.
*
*/
namespace WTF {
class CrashOnOverflow {
protected:
void overflowed()
{
CRASH();
}
void clearOverflow() { }
public:
bool hasOverflowed() const { return false; }
};
class RecordOverflow {
protected:
RecordOverflow()
: m_overflowed(false)
{
}
void overflowed()
{
m_overflowed = true;
}
void clearOverflow()
{
m_overflowed = false;
}
public:
bool hasOverflowed() const { return m_overflowed; }
private:
unsigned char m_overflowed;
};
template <typename T, class OverflowHandler = CrashOnOverflow> class Checked;
template <typename T> struct RemoveChecked;
template <typename T> struct RemoveChecked<Checked<T> >;
template <typename Target, typename Source, bool targetSigned = ::std::numeric_limits<Target>::is_signed, bool sourceSigned = ::std::numeric_limits<Source>::is_signed> struct BoundsChecker;
template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false> {
static bool inBounds(Source value)
{
// Same signedness so implicit type conversion will always increase precision
// to widest type
return value <= ::std::numeric_limits<Target>::max();
}
};
template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true> {
static bool inBounds(Source value)
{
// Same signedness so implicit type conversion will always increase precision
// to widest type
return ::std::numeric_limits<Target>::min() <= value && value <= ::std::numeric_limits<Target>::max();
}
};
template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true> {
static bool inBounds(Source value)
{
// Target is unsigned so any value less than zero is clearly unsafe
if (value < 0)
return false;
// If our (unsigned) Target is the same or greater width we can
// convert value to type Target without losing precision
if (sizeof(Target) >= sizeof(Source))
return static_cast<Target>(value) <= ::std::numeric_limits<Target>::max();
// The signed Source type has greater precision than the target so
// max(Target) -> Source will widen.
return value <= static_cast<Source>(::std::numeric_limits<Target>::max());
}
};
template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false> {
static bool inBounds(Source value)
{
// Signed target with an unsigned source
if (sizeof(Target) <= sizeof(Source))
return value <= static_cast<Source>(::std::numeric_limits<Target>::max());
// Target is Wider than Source so we're guaranteed to fit any value in
// unsigned Source
return true;
}
};
template <typename Target, typename Source, bool SameType = IsSameType<Target, Source>::value> struct BoundsCheckElider;
template <typename Target, typename Source> struct BoundsCheckElider<Target, Source, true> {
static bool inBounds(Source) { return true; }
};
template <typename Target, typename Source> struct BoundsCheckElider<Target, Source, false> : public BoundsChecker<Target, Source> {
};
template <typename Target, typename Source> static inline bool isInBounds(Source value)
{
return BoundsCheckElider<Target, Source>::inBounds(value);
}
template <typename T> struct RemoveChecked {
typedef T CleanType;
static const CleanType DefaultValue = 0;
};
template <typename T> struct RemoveChecked<Checked<T, CrashOnOverflow> > {
typedef typename RemoveChecked<T>::CleanType CleanType;
static const CleanType DefaultValue = 0;
};
template <typename T> struct RemoveChecked<Checked<T, RecordOverflow> > {
typedef typename RemoveChecked<T>::CleanType CleanType;
static const CleanType DefaultValue = 0;
};
// The ResultBase and SignednessSelector are used to workaround typeof not being
// available in MSVC
template <typename U, typename V, bool uIsBigger = (sizeof(U) > sizeof(V)), bool sameSize = (sizeof(U) == sizeof(V))> struct ResultBase;
template <typename U, typename V> struct ResultBase<U, V, true, false> {
typedef U ResultType;
};
template <typename U, typename V> struct ResultBase<U, V, false, false> {
typedef V ResultType;
};
template <typename U> struct ResultBase<U, U, false, true> {
typedef U ResultType;
};
template <typename U, typename V, bool uIsSigned = ::std::numeric_limits<U>::is_signed, bool vIsSigned = ::std::numeric_limits<V>::is_signed> struct SignednessSelector;
template <typename U, typename V> struct SignednessSelector<U, V, true, true> {
typedef U ResultType;
};
template <typename U, typename V> struct SignednessSelector<U, V, false, false> {
typedef U ResultType;
};
template <typename U, typename V> struct SignednessSelector<U, V, true, false> {
typedef V ResultType;
};
template <typename U, typename V> struct SignednessSelector<U, V, false, true> {
typedef U ResultType;
};
template <typename U, typename V> struct ResultBase<U, V, false, true> {
typedef typename SignednessSelector<U, V>::ResultType ResultType;
};
template <typename U, typename V> struct Result : ResultBase<typename RemoveChecked<U>::CleanType, typename RemoveChecked<V>::CleanType> {
};
template <typename LHS, typename RHS, typename ResultType = typename Result<LHS, RHS>::ResultType,
bool lhsSigned = ::std::numeric_limits<LHS>::is_signed, bool rhsSigned = ::std::numeric_limits<RHS>::is_signed> struct ArithmeticOperations;
template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, true, true> {
// LHS and RHS are signed types
// Helper function
static inline bool signsMatch(LHS lhs, RHS rhs)
{
return (lhs ^ rhs) >= 0;
}
static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
{
if (signsMatch(lhs, rhs)) {
if (lhs >= 0) {
if ((::std::numeric_limits<ResultType>::max() - rhs) < lhs)
return false;
} else {
ResultType temp = lhs - ::std::numeric_limits<ResultType>::min();
if (rhs < -temp)
return false;
}
} // if the signs do not match this operation can't overflow
result = lhs + rhs;
return true;
}
static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
{
if (!signsMatch(lhs, rhs)) {
if (lhs >= 0) {
if (lhs > ::std::numeric_limits<ResultType>::max() + rhs)
return false;
} else {
if (rhs > ::std::numeric_limits<ResultType>::max() + lhs)
return false;
}
} // if the signs match this operation can't overflow
result = lhs - rhs;
return true;
}
static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
{
if (signsMatch(lhs, rhs)) {
if (lhs >= 0) {
if (lhs && (::std::numeric_limits<ResultType>::max() / lhs) < rhs)
return false;
} else {
if (lhs == ::std::numeric_limits<ResultType>::min() || rhs == ::std::numeric_limits<ResultType>::min())
return false;
if ((::std::numeric_limits<ResultType>::max() / -lhs) < -rhs)
return false;
}
} else {
if (lhs < 0) {
if (rhs && lhs < (::std::numeric_limits<ResultType>::min() / rhs))
return false;
} else {
if (lhs && rhs < (::std::numeric_limits<ResultType>::min() / lhs))
return false;
}
}
result = lhs * rhs;
return true;
}
static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; }
};
template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, false, false> {
// LHS and RHS are unsigned types so bounds checks are nice and easy
static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
{
ResultType temp = lhs + rhs;
if (temp < lhs)
return false;
result = temp;
return true;
}
static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
{
ResultType temp = lhs - rhs;
if (temp > lhs)
return false;
result = temp;
return true;
}
static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
{
ResultType temp = lhs * rhs;
if (temp < lhs)
return false;
result = temp;
return true;
}
static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; }
};
template <typename ResultType> struct ArithmeticOperations<int, unsigned, ResultType, true, false> {
static inline bool add(int64_t lhs, int64_t rhs, ResultType& result)
{
int64_t temp = lhs + rhs;
if (temp < ::std::numeric_limits<ResultType>::min())
return false;
if (temp > ::std::numeric_limits<ResultType>::max())
return false;
result = static_cast<ResultType>(temp);
return true;
}
static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result)
{
int64_t temp = lhs - rhs;
if (temp < ::std::numeric_limits<ResultType>::min())
return false;
if (temp > ::std::numeric_limits<ResultType>::max())
return false;
result = static_cast<ResultType>(temp);
return true;
}
static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result)
{
int64_t temp = lhs * rhs;
if (temp < ::std::numeric_limits<ResultType>::min())
return false;
if (temp > ::std::numeric_limits<ResultType>::max())
return false;
result = static_cast<ResultType>(temp);
return true;
}
static inline bool equals(int lhs, unsigned rhs)
{
return static_cast<int64_t>(lhs) == static_cast<int64_t>(rhs);
}
};
template <typename ResultType> struct ArithmeticOperations<unsigned, int, ResultType, false, true> {
static inline bool add(int64_t lhs, int64_t rhs, ResultType& result)
{
return ArithmeticOperations<int, unsigned, ResultType>::add(rhs, lhs, result);
}
static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result)
{
return ArithmeticOperations<int, unsigned, ResultType>::sub(lhs, rhs, result);
}
static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result)
{
return ArithmeticOperations<int, unsigned, ResultType>::multiply(rhs, lhs, result);
}
static inline bool equals(unsigned lhs, int rhs)
{
return ArithmeticOperations<int, unsigned, ResultType>::equals(rhs, lhs);
}
};
template <typename U, typename V, typename R> static inline bool safeAdd(U lhs, V rhs, R& result)
{
return ArithmeticOperations<U, V, R>::add(lhs, rhs, result);
}
template <typename U, typename V, typename R> static inline bool safeSub(U lhs, V rhs, R& result)
{
return ArithmeticOperations<U, V, R>::sub(lhs, rhs, result);
}
template <typename U, typename V, typename R> static inline bool safeMultiply(U lhs, V rhs, R& result)
{
return ArithmeticOperations<U, V, R>::multiply(lhs, rhs, result);
}
template <typename U, typename V> static inline bool safeEquals(U lhs, V rhs)
{
return ArithmeticOperations<U, V>::equals(lhs, rhs);
}
enum ResultOverflowedTag { ResultOverflowed };
// FIXME: Needed to workaround http://llvm.org/bugs/show_bug.cgi?id=10801
static inline bool workAroundClangBug() { return true; }
template <typename T, class OverflowHandler> class Checked : public OverflowHandler {
public:
template <typename _T, class _OverflowHandler> friend class Checked;
Checked()
: m_value(0)
{
}
Checked(ResultOverflowedTag)
: m_value(0)
{
// FIXME: Remove this when clang fixes http://llvm.org/bugs/show_bug.cgi?id=10801
if (workAroundClangBug())
this->overflowed();
}
template <typename U> Checked(U value)
{
if (!isInBounds<T>(value))
this->overflowed();
m_value = static_cast<T>(value);
}
template <typename V> Checked(const Checked<T, V>& rhs)
: m_value(rhs.m_value)
{
if (rhs.hasOverflowed())
this->overflowed();
}
template <typename U> Checked(const Checked<U, OverflowHandler>& rhs)
: OverflowHandler(rhs)
{
if (!isInBounds<T>(rhs.m_value))
this->overflowed();
m_value = static_cast<T>(rhs.m_value);
}
template <typename U, typename V> Checked(const Checked<U, V>& rhs)
{
if (rhs.hasOverflowed())
this->overflowed();
if (!isInBounds<T>(rhs.m_value))
this->overflowed();
m_value = static_cast<T>(rhs.m_value);
}
const Checked& operator=(Checked rhs)
{
this->clearOverflow();
if (rhs.hasOverflowed())
this->overflowed();
m_value = static_cast<T>(rhs.m_value);
return *this;
}
template <typename U> const Checked& operator=(U value)
{
return *this = Checked(value);
}
template <typename U, typename V> const Checked& operator=(const Checked<U, V>& rhs)
{
return *this = Checked(rhs);
}
// prefix
const Checked& operator++()
{
if (m_value == ::std::numeric_limits<T>::max())
this->overflowed();
m_value++;
return *this;
}
const Checked& operator--()
{
if (m_value == ::std::numeric_limits<T>::min())
this->overflowed();
m_value--;
return *this;
}
// postfix operators
const Checked operator++(int)
{
if (m_value == ::std::numeric_limits<T>::max())
this->overflowed();
return Checked(m_value++);
}
const Checked operator--(int)
{
if (m_value == ::std::numeric_limits<T>::min())
this->overflowed();
return Checked(m_value--);
}
// Boolean operators
bool operator!() const
{
if (this->hasOverflowed())
CRASH();
return !m_value;
}
typedef void* (Checked::*UnspecifiedBoolType);
operator UnspecifiedBoolType*() const
{
if (this->hasOverflowed())
CRASH();
return (m_value) ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0;
}
// Value accessors. unsafeGet() will crash if there's been an overflow.
T unsafeGet() const
{
if (this->hasOverflowed())
CRASH();
return m_value;
}
bool safeGet(T& value) const WARN_UNUSED_RETURN
{
value = m_value;
return this->hasOverflowed();
}
// Mutating assignment
template <typename U> const Checked operator+=(U rhs)
{
if (!safeAdd(m_value, rhs, m_value))
this->overflowed();
return *this;
}
template <typename U> const Checked operator-=(U rhs)
{
if (!safeSub(m_value, rhs, m_value))
this->overflowed();
return *this;
}
template <typename U> const Checked operator*=(U rhs)
{
if (!safeMultiply(m_value, rhs, m_value))
this->overflowed();
return *this;
}
const Checked operator*=(double rhs)
{
double result = rhs * m_value;
// Handle +/- infinity and NaN
if (!(::std::numeric_limits<T>::min() <= result && ::std::numeric_limits<T>::max() >= result))
this->overflowed();
m_value = (T)result;
return *this;
}
const Checked operator*=(float rhs)
{
return *this *= (double)rhs;
}
template <typename U, typename V> const Checked operator+=(Checked<U, V> rhs)
{
if (rhs.hasOverflowed())
this->overflowed();
return *this += rhs.m_value;
}
template <typename U, typename V> const Checked operator-=(Checked<U, V> rhs)
{
if (rhs.hasOverflowed())
this->overflowed();
return *this -= rhs.m_value;
}
template <typename U, typename V> const Checked operator*=(Checked<U, V> rhs)
{
if (rhs.hasOverflowed())
this->overflowed();
return *this *= rhs.m_value;
}
// Equality comparisons
template <typename V> bool operator==(Checked<T, V> rhs)
{
return unsafeGet() == rhs.unsafeGet();
}
template <typename U> bool operator==(U rhs)
{
if (this->hasOverflowed())
this->overflowed();
return safeEquals(m_value, rhs);
}
template <typename U, typename V> const Checked operator==(Checked<U, V> rhs)
{
return unsafeGet() == Checked(rhs.unsafeGet());
}
template <typename U> bool operator!=(U rhs)
{
return !(*this == rhs);
}
private:
// Disallow implicit conversion of floating point to integer types
Checked(float);
Checked(double);
void operator=(float);
void operator=(double);
void operator+=(float);
void operator+=(double);
void operator-=(float);
void operator-=(double);
T m_value;
};
template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs)
{
U x = 0;
V y = 0;
bool overflowed = lhs.safeGet(x) || rhs.safeGet(y);
typename Result<U, V>::ResultType result = 0;
overflowed |= !safeAdd(x, y, result);
if (overflowed)
return ResultOverflowed;
return result;
}
template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs)
{
U x = 0;
V y = 0;
bool overflowed = lhs.safeGet(x) || rhs.safeGet(y);
typename Result<U, V>::ResultType result = 0;
overflowed |= !safeSub(x, y, result);
if (overflowed)
return ResultOverflowed;
return result;
}
template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs)
{
U x = 0;
V y = 0;
bool overflowed = lhs.safeGet(x) || rhs.safeGet(y);
typename Result<U, V>::ResultType result = 0;
overflowed |= !safeMultiply(x, y, result);
if (overflowed)
return ResultOverflowed;
return result;
}
template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(Checked<U, OverflowHandler> lhs, V rhs)
{
return lhs + Checked<V, OverflowHandler>(rhs);
}
template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(Checked<U, OverflowHandler> lhs, V rhs)
{
return lhs - Checked<V, OverflowHandler>(rhs);
}
template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(Checked<U, OverflowHandler> lhs, V rhs)
{
return lhs * Checked<V, OverflowHandler>(rhs);
}
template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(U lhs, Checked<V, OverflowHandler> rhs)
{
return Checked<U, OverflowHandler>(lhs) + rhs;
}
template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(U lhs, Checked<V, OverflowHandler> rhs)
{
return Checked<U, OverflowHandler>(lhs) - rhs;
}
template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(U lhs, Checked<V, OverflowHandler> rhs)
{
return Checked<U, OverflowHandler>(lhs) * rhs;
}
}
using WTF::Checked;
using WTF::RecordOverflow;
#endif

73
js/src/yarr/MatchResult.h Normal file
Просмотреть файл

@ -0,0 +1,73 @@
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MatchResult_h
#define MatchResult_h
#include "wtfbridge.h"
typedef uint64_t EncodedMatchResult;
struct MatchResult {
MatchResult(size_t start, size_t end)
: start(start)
, end(end)
{
}
explicit MatchResult(EncodedMatchResult encoded)
{
union u {
uint64_t encoded;
struct s {
size_t start;
size_t end;
} split;
} value;
value.encoded = encoded;
start = value.split.start;
end = value.split.end;
}
static MatchResult failed()
{
return MatchResult(WTF::notFound, 0);
}
operator bool()
{
return start != WTF::notFound;
}
bool empty()
{
return start == end;
}
size_t start;
size_t end;
};
#endif

261
js/src/yarr/TypeTraits.h Normal file
Просмотреть файл

@ -0,0 +1,261 @@
/*
* Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2009, 2010 Google Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#ifndef TypeTraits_h
#define TypeTraits_h
#include "assembler/wtf/Platform.h"
#if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600))
#include <type_traits>
#if defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)
#include <tr1/memory>
#endif
#endif
namespace WTF {
// The following are provided in this file:
//
// Conditional<Predicate, If, Then>::Type
//
// IsInteger<T>::value
// IsPod<T>::value, see the definition for a note about its limitations
// IsConvertibleToInteger<T>::value
//
// IsArray<T>::value
//
// IsSameType<T, U>::value
//
// RemovePointer<T>::Type
// RemoveReference<T>::Type
// RemoveConst<T>::Type
// RemoveVolatile<T>::Type
// RemoveConstVolatile<T>::Type
// RemoveExtent<T>::Type
//
// DecayArray<T>::Type
//
// COMPILE_ASSERT's in TypeTraits.cpp illustrate their usage and what they do.
template <bool Predicate, class If, class Then> struct Conditional { typedef If Type; };
template <class If, class Then> struct Conditional<false, If, Then> { typedef Then Type; };
template<typename T> struct IsInteger { static const bool value = false; };
template<> struct IsInteger<bool> { static const bool value = true; };
template<> struct IsInteger<char> { static const bool value = true; };
template<> struct IsInteger<signed char> { static const bool value = true; };
template<> struct IsInteger<unsigned char> { static const bool value = true; };
template<> struct IsInteger<short> { static const bool value = true; };
template<> struct IsInteger<unsigned short> { static const bool value = true; };
template<> struct IsInteger<int> { static const bool value = true; };
template<> struct IsInteger<unsigned int> { static const bool value = true; };
template<> struct IsInteger<long> { static const bool value = true; };
template<> struct IsInteger<unsigned long> { static const bool value = true; };
template<> struct IsInteger<long long> { static const bool value = true; };
template<> struct IsInteger<unsigned long long> { static const bool value = true; };
#if WTF_COMPILER_MSVC || defined(_NATIVE_WCHAR_T_DEFINED)
template<> struct IsInteger<wchar_t> { static const bool value = true; };
#endif
template<typename T> struct IsFloatingPoint { static const bool value = false; };
template<> struct IsFloatingPoint<float> { static const bool value = true; };
template<> struct IsFloatingPoint<double> { static const bool value = true; };
template<> struct IsFloatingPoint<long double> { static const bool value = true; };
template<typename T> struct IsArithmetic { static const bool value = IsInteger<T>::value || IsFloatingPoint<T>::value; };
// IsPod is misnamed as it doesn't cover all plain old data (pod) types.
// Specifically, it doesn't allow for enums or for structs.
template <typename T> struct IsPod { static const bool value = IsArithmetic<T>::value; };
template <typename P> struct IsPod<P*> { static const bool value = true; };
template<typename T> class IsConvertibleToInteger {
// Avoid "possible loss of data" warning when using Microsoft's C++ compiler
// by not converting int's to doubles.
template<bool performCheck, typename U> class IsConvertibleToDouble;
template<typename U> class IsConvertibleToDouble<false, U> {
public:
static const bool value = false;
};
template<typename U> class IsConvertibleToDouble<true, U> {
typedef char YesType;
struct NoType {
char padding[8];
};
static YesType floatCheck(long double);
static NoType floatCheck(...);
static T& t;
public:
static const bool value = sizeof(floatCheck(t)) == sizeof(YesType);
};
public:
static const bool value = IsInteger<T>::value || IsConvertibleToDouble<!IsInteger<T>::value, T>::value;
};
template <class T> struct IsArray {
static const bool value = false;
};
template <class T> struct IsArray<T[]> {
static const bool value = true;
};
template <class T, size_t N> struct IsArray<T[N]> {
static const bool value = true;
};
template <typename T, typename U> struct IsSameType {
static const bool value = false;
};
template <typename T> struct IsSameType<T, T> {
static const bool value = true;
};
template <typename T, typename U> class IsSubclass {
typedef char YesType;
struct NoType {
char padding[8];
};
static YesType subclassCheck(U*);
static NoType subclassCheck(...);
static T* t;
public:
static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
};
template <typename T, template<class V> class U> class IsSubclassOfTemplate {
typedef char YesType;
struct NoType {
char padding[8];
};
template<typename W> static YesType subclassCheck(U<W>*);
static NoType subclassCheck(...);
static T* t;
public:
static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
};
template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate {
typedef T Type;
};
template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate<OuterTemplate<T>, OuterTemplate> {
typedef T Type;
};
template <typename T> struct RemoveConst {
typedef T Type;
};
template <typename T> struct RemoveConst<const T> {
typedef T Type;
};
template <typename T> struct RemoveVolatile {
typedef T Type;
};
template <typename T> struct RemoveVolatile<volatile T> {
typedef T Type;
};
template <typename T> struct RemoveConstVolatile {
typedef typename RemoveVolatile<typename RemoveConst<T>::Type>::Type Type;
};
template <typename T> struct RemovePointer {
typedef T Type;
};
template <typename T> struct RemovePointer<T*> {
typedef T Type;
};
template <typename T> struct RemoveReference {
typedef T Type;
};
template <typename T> struct RemoveReference<T&> {
typedef T Type;
};
template <typename T> struct RemoveExtent {
typedef T Type;
};
template <typename T> struct RemoveExtent<T[]> {
typedef T Type;
};
template <typename T, size_t N> struct RemoveExtent<T[N]> {
typedef T Type;
};
template <class T> struct DecayArray {
typedef typename RemoveReference<T>::Type U;
public:
typedef typename Conditional<
IsArray<U>::value,
typename RemoveExtent<U>::Type*,
typename RemoveConstVolatile<U>::Type
>::Type Type;
};
#if WTF_COMPILER_CLANG || GCC_VERSION_AT_LEAST(4, 6, 0) || (defined(_MSC_VER) && (_MSC_VER >= 1400) && (_MSC_VER < 1600) && !defined(__INTEL_COMPILER))
// VC8 (VS2005) and later has __has_trivial_constructor and __has_trivial_destructor,
// but the implementation returns false for built-in types. We add the extra IsPod condition to
// work around this.
template <typename T> struct HasTrivialConstructor {
static const bool value = __has_trivial_constructor(T) || IsPod<RemoveConstVolatile<T> >::value;
};
template <typename T> struct HasTrivialDestructor {
static const bool value = __has_trivial_destructor(T) || IsPod<RemoveConstVolatile<T> >::value;
};
#elif (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600))
// GCC's libstdc++ 20070724 and later supports C++ TR1 type_traits in the std namespace.
// VC10 (VS2010) and later support C++ TR1 type_traits in the std::tr1 namespace.
template<typename T> struct HasTrivialConstructor : public std::tr1::has_trivial_constructor<T> { };
template<typename T> struct HasTrivialDestructor : public std::tr1::has_trivial_destructor<T> { };
#else
// For compilers that don't support detection of trivial constructors and destructors in classes,
// we use a template that returns true for any POD type that IsPod can detect (see IsPod caveats above),
// but false for all other types (which includes all classes). This will give false negatives, which can hurt
// performance, but avoids false positives, which would result in incorrect behavior.
template <typename T> struct HasTrivialConstructor {
static const bool value = IsPod<RemoveConstVolatile<T> >::value;
};
template <typename T> struct HasTrivialDestructor {
static const bool value = IsPod<RemoveConstVolatile<T> >::value;
};
#endif
} // namespace WTF
#endif // TypeTraits_h

Просмотреть файл

@ -1,7 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
* Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged
* All rights reserved.
@ -26,14 +23,12 @@
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***** END LICENSE BLOCK ***** */
*/
#ifndef Yarr_h
#define Yarr_h
#include <limits.h>
#include "YarrInterpreter.h"
#include "YarrPattern.h"
@ -49,6 +44,7 @@ namespace JSC { namespace Yarr {
#define YarrStackSpaceForBackTrackInfoParentheses 2
static const unsigned quantifyInfinite = UINT_MAX;
static const unsigned offsetNoMatch = (unsigned)-1;
// The below limit restricts the number of "recursive" match calls in order to
// avoid spending exponential time on complex regular expressions.
@ -63,8 +59,10 @@ enum JSRegExpResult {
JSRegExpErrorInternal = -4
};
PassOwnPtr<BytecodePattern> byteCompile(YarrPattern&, BumpPointerAllocator*);
int interpret(BytecodePattern*, const UChar* input, unsigned start, unsigned length, int* output);
enum YarrCharSize {
Char8,
Char16
};
} } // namespace JSC::Yarr

Просмотреть файл

@ -0,0 +1,463 @@
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// DO NOT EDIT! - this file autogenerated by YarrCanonicalizeUCS2.js
#include "YarrCanonicalizeUCS2.h"
namespace JSC { namespace Yarr {
#include <stddef.h>
#include <stdint.h>
uint16_t ucs2CharacterSet0[] = { 0x01c4u, 0x01c5u, 0x01c6u, 0 };
uint16_t ucs2CharacterSet1[] = { 0x01c7u, 0x01c8u, 0x01c9u, 0 };
uint16_t ucs2CharacterSet2[] = { 0x01cau, 0x01cbu, 0x01ccu, 0 };
uint16_t ucs2CharacterSet3[] = { 0x01f1u, 0x01f2u, 0x01f3u, 0 };
uint16_t ucs2CharacterSet4[] = { 0x0392u, 0x03b2u, 0x03d0u, 0 };
uint16_t ucs2CharacterSet5[] = { 0x0395u, 0x03b5u, 0x03f5u, 0 };
uint16_t ucs2CharacterSet6[] = { 0x0398u, 0x03b8u, 0x03d1u, 0 };
uint16_t ucs2CharacterSet7[] = { 0x0345u, 0x0399u, 0x03b9u, 0x1fbeu, 0 };
uint16_t ucs2CharacterSet8[] = { 0x039au, 0x03bau, 0x03f0u, 0 };
uint16_t ucs2CharacterSet9[] = { 0x00b5u, 0x039cu, 0x03bcu, 0 };
uint16_t ucs2CharacterSet10[] = { 0x03a0u, 0x03c0u, 0x03d6u, 0 };
uint16_t ucs2CharacterSet11[] = { 0x03a1u, 0x03c1u, 0x03f1u, 0 };
uint16_t ucs2CharacterSet12[] = { 0x03a3u, 0x03c2u, 0x03c3u, 0 };
uint16_t ucs2CharacterSet13[] = { 0x03a6u, 0x03c6u, 0x03d5u, 0 };
uint16_t ucs2CharacterSet14[] = { 0x1e60u, 0x1e61u, 0x1e9bu, 0 };
static const size_t UCS2_CANONICALIZATION_SETS = 15;
uint16_t* characterSetInfo[UCS2_CANONICALIZATION_SETS] = {
ucs2CharacterSet0,
ucs2CharacterSet1,
ucs2CharacterSet2,
ucs2CharacterSet3,
ucs2CharacterSet4,
ucs2CharacterSet5,
ucs2CharacterSet6,
ucs2CharacterSet7,
ucs2CharacterSet8,
ucs2CharacterSet9,
ucs2CharacterSet10,
ucs2CharacterSet11,
ucs2CharacterSet12,
ucs2CharacterSet13,
ucs2CharacterSet14,
};
const size_t UCS2_CANONICALIZATION_RANGES = 364;
UCS2CanonicalizationRange rangeInfo[UCS2_CANONICALIZATION_RANGES] = {
{ 0x0000u, 0x0040u, 0x0000u, CanonicalizeUnique },
{ 0x0041u, 0x005au, 0x0020u, CanonicalizeRangeLo },
{ 0x005bu, 0x0060u, 0x0000u, CanonicalizeUnique },
{ 0x0061u, 0x007au, 0x0020u, CanonicalizeRangeHi },
{ 0x007bu, 0x00b4u, 0x0000u, CanonicalizeUnique },
{ 0x00b5u, 0x00b5u, 0x0009u, CanonicalizeSet },
{ 0x00b6u, 0x00bfu, 0x0000u, CanonicalizeUnique },
{ 0x00c0u, 0x00d6u, 0x0020u, CanonicalizeRangeLo },
{ 0x00d7u, 0x00d7u, 0x0000u, CanonicalizeUnique },
{ 0x00d8u, 0x00deu, 0x0020u, CanonicalizeRangeLo },
{ 0x00dfu, 0x00dfu, 0x0000u, CanonicalizeUnique },
{ 0x00e0u, 0x00f6u, 0x0020u, CanonicalizeRangeHi },
{ 0x00f7u, 0x00f7u, 0x0000u, CanonicalizeUnique },
{ 0x00f8u, 0x00feu, 0x0020u, CanonicalizeRangeHi },
{ 0x00ffu, 0x00ffu, 0x0079u, CanonicalizeRangeLo },
{ 0x0100u, 0x012fu, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x0130u, 0x0131u, 0x0000u, CanonicalizeUnique },
{ 0x0132u, 0x0137u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x0138u, 0x0138u, 0x0000u, CanonicalizeUnique },
{ 0x0139u, 0x0148u, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x0149u, 0x0149u, 0x0000u, CanonicalizeUnique },
{ 0x014au, 0x0177u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x0178u, 0x0178u, 0x0079u, CanonicalizeRangeHi },
{ 0x0179u, 0x017eu, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x017fu, 0x017fu, 0x0000u, CanonicalizeUnique },
{ 0x0180u, 0x0180u, 0x00c3u, CanonicalizeRangeLo },
{ 0x0181u, 0x0181u, 0x00d2u, CanonicalizeRangeLo },
{ 0x0182u, 0x0185u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x0186u, 0x0186u, 0x00ceu, CanonicalizeRangeLo },
{ 0x0187u, 0x0188u, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x0189u, 0x018au, 0x00cdu, CanonicalizeRangeLo },
{ 0x018bu, 0x018cu, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x018du, 0x018du, 0x0000u, CanonicalizeUnique },
{ 0x018eu, 0x018eu, 0x004fu, CanonicalizeRangeLo },
{ 0x018fu, 0x018fu, 0x00cau, CanonicalizeRangeLo },
{ 0x0190u, 0x0190u, 0x00cbu, CanonicalizeRangeLo },
{ 0x0191u, 0x0192u, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x0193u, 0x0193u, 0x00cdu, CanonicalizeRangeLo },
{ 0x0194u, 0x0194u, 0x00cfu, CanonicalizeRangeLo },
{ 0x0195u, 0x0195u, 0x0061u, CanonicalizeRangeLo },
{ 0x0196u, 0x0196u, 0x00d3u, CanonicalizeRangeLo },
{ 0x0197u, 0x0197u, 0x00d1u, CanonicalizeRangeLo },
{ 0x0198u, 0x0199u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x019au, 0x019au, 0x00a3u, CanonicalizeRangeLo },
{ 0x019bu, 0x019bu, 0x0000u, CanonicalizeUnique },
{ 0x019cu, 0x019cu, 0x00d3u, CanonicalizeRangeLo },
{ 0x019du, 0x019du, 0x00d5u, CanonicalizeRangeLo },
{ 0x019eu, 0x019eu, 0x0082u, CanonicalizeRangeLo },
{ 0x019fu, 0x019fu, 0x00d6u, CanonicalizeRangeLo },
{ 0x01a0u, 0x01a5u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x01a6u, 0x01a6u, 0x00dau, CanonicalizeRangeLo },
{ 0x01a7u, 0x01a8u, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x01a9u, 0x01a9u, 0x00dau, CanonicalizeRangeLo },
{ 0x01aau, 0x01abu, 0x0000u, CanonicalizeUnique },
{ 0x01acu, 0x01adu, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x01aeu, 0x01aeu, 0x00dau, CanonicalizeRangeLo },
{ 0x01afu, 0x01b0u, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x01b1u, 0x01b2u, 0x00d9u, CanonicalizeRangeLo },
{ 0x01b3u, 0x01b6u, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x01b7u, 0x01b7u, 0x00dbu, CanonicalizeRangeLo },
{ 0x01b8u, 0x01b9u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x01bau, 0x01bbu, 0x0000u, CanonicalizeUnique },
{ 0x01bcu, 0x01bdu, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x01beu, 0x01beu, 0x0000u, CanonicalizeUnique },
{ 0x01bfu, 0x01bfu, 0x0038u, CanonicalizeRangeLo },
{ 0x01c0u, 0x01c3u, 0x0000u, CanonicalizeUnique },
{ 0x01c4u, 0x01c6u, 0x0000u, CanonicalizeSet },
{ 0x01c7u, 0x01c9u, 0x0001u, CanonicalizeSet },
{ 0x01cau, 0x01ccu, 0x0002u, CanonicalizeSet },
{ 0x01cdu, 0x01dcu, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x01ddu, 0x01ddu, 0x004fu, CanonicalizeRangeHi },
{ 0x01deu, 0x01efu, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x01f0u, 0x01f0u, 0x0000u, CanonicalizeUnique },
{ 0x01f1u, 0x01f3u, 0x0003u, CanonicalizeSet },
{ 0x01f4u, 0x01f5u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x01f6u, 0x01f6u, 0x0061u, CanonicalizeRangeHi },
{ 0x01f7u, 0x01f7u, 0x0038u, CanonicalizeRangeHi },
{ 0x01f8u, 0x021fu, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x0220u, 0x0220u, 0x0082u, CanonicalizeRangeHi },
{ 0x0221u, 0x0221u, 0x0000u, CanonicalizeUnique },
{ 0x0222u, 0x0233u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x0234u, 0x0239u, 0x0000u, CanonicalizeUnique },
{ 0x023au, 0x023au, 0x2a2bu, CanonicalizeRangeLo },
{ 0x023bu, 0x023cu, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x023du, 0x023du, 0x00a3u, CanonicalizeRangeHi },
{ 0x023eu, 0x023eu, 0x2a28u, CanonicalizeRangeLo },
{ 0x023fu, 0x0240u, 0x2a3fu, CanonicalizeRangeLo },
{ 0x0241u, 0x0242u, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x0243u, 0x0243u, 0x00c3u, CanonicalizeRangeHi },
{ 0x0244u, 0x0244u, 0x0045u, CanonicalizeRangeLo },
{ 0x0245u, 0x0245u, 0x0047u, CanonicalizeRangeLo },
{ 0x0246u, 0x024fu, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x0250u, 0x0250u, 0x2a1fu, CanonicalizeRangeLo },
{ 0x0251u, 0x0251u, 0x2a1cu, CanonicalizeRangeLo },
{ 0x0252u, 0x0252u, 0x2a1eu, CanonicalizeRangeLo },
{ 0x0253u, 0x0253u, 0x00d2u, CanonicalizeRangeHi },
{ 0x0254u, 0x0254u, 0x00ceu, CanonicalizeRangeHi },
{ 0x0255u, 0x0255u, 0x0000u, CanonicalizeUnique },
{ 0x0256u, 0x0257u, 0x00cdu, CanonicalizeRangeHi },
{ 0x0258u, 0x0258u, 0x0000u, CanonicalizeUnique },
{ 0x0259u, 0x0259u, 0x00cau, CanonicalizeRangeHi },
{ 0x025au, 0x025au, 0x0000u, CanonicalizeUnique },
{ 0x025bu, 0x025bu, 0x00cbu, CanonicalizeRangeHi },
{ 0x025cu, 0x025fu, 0x0000u, CanonicalizeUnique },
{ 0x0260u, 0x0260u, 0x00cdu, CanonicalizeRangeHi },
{ 0x0261u, 0x0262u, 0x0000u, CanonicalizeUnique },
{ 0x0263u, 0x0263u, 0x00cfu, CanonicalizeRangeHi },
{ 0x0264u, 0x0264u, 0x0000u, CanonicalizeUnique },
{ 0x0265u, 0x0265u, 0xa528u, CanonicalizeRangeLo },
{ 0x0266u, 0x0267u, 0x0000u, CanonicalizeUnique },
{ 0x0268u, 0x0268u, 0x00d1u, CanonicalizeRangeHi },
{ 0x0269u, 0x0269u, 0x00d3u, CanonicalizeRangeHi },
{ 0x026au, 0x026au, 0x0000u, CanonicalizeUnique },
{ 0x026bu, 0x026bu, 0x29f7u, CanonicalizeRangeLo },
{ 0x026cu, 0x026eu, 0x0000u, CanonicalizeUnique },
{ 0x026fu, 0x026fu, 0x00d3u, CanonicalizeRangeHi },
{ 0x0270u, 0x0270u, 0x0000u, CanonicalizeUnique },
{ 0x0271u, 0x0271u, 0x29fdu, CanonicalizeRangeLo },
{ 0x0272u, 0x0272u, 0x00d5u, CanonicalizeRangeHi },
{ 0x0273u, 0x0274u, 0x0000u, CanonicalizeUnique },
{ 0x0275u, 0x0275u, 0x00d6u, CanonicalizeRangeHi },
{ 0x0276u, 0x027cu, 0x0000u, CanonicalizeUnique },
{ 0x027du, 0x027du, 0x29e7u, CanonicalizeRangeLo },
{ 0x027eu, 0x027fu, 0x0000u, CanonicalizeUnique },
{ 0x0280u, 0x0280u, 0x00dau, CanonicalizeRangeHi },
{ 0x0281u, 0x0282u, 0x0000u, CanonicalizeUnique },
{ 0x0283u, 0x0283u, 0x00dau, CanonicalizeRangeHi },
{ 0x0284u, 0x0287u, 0x0000u, CanonicalizeUnique },
{ 0x0288u, 0x0288u, 0x00dau, CanonicalizeRangeHi },
{ 0x0289u, 0x0289u, 0x0045u, CanonicalizeRangeHi },
{ 0x028au, 0x028bu, 0x00d9u, CanonicalizeRangeHi },
{ 0x028cu, 0x028cu, 0x0047u, CanonicalizeRangeHi },
{ 0x028du, 0x0291u, 0x0000u, CanonicalizeUnique },
{ 0x0292u, 0x0292u, 0x00dbu, CanonicalizeRangeHi },
{ 0x0293u, 0x0344u, 0x0000u, CanonicalizeUnique },
{ 0x0345u, 0x0345u, 0x0007u, CanonicalizeSet },
{ 0x0346u, 0x036fu, 0x0000u, CanonicalizeUnique },
{ 0x0370u, 0x0373u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x0374u, 0x0375u, 0x0000u, CanonicalizeUnique },
{ 0x0376u, 0x0377u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x0378u, 0x037au, 0x0000u, CanonicalizeUnique },
{ 0x037bu, 0x037du, 0x0082u, CanonicalizeRangeLo },
{ 0x037eu, 0x0385u, 0x0000u, CanonicalizeUnique },
{ 0x0386u, 0x0386u, 0x0026u, CanonicalizeRangeLo },
{ 0x0387u, 0x0387u, 0x0000u, CanonicalizeUnique },
{ 0x0388u, 0x038au, 0x0025u, CanonicalizeRangeLo },
{ 0x038bu, 0x038bu, 0x0000u, CanonicalizeUnique },
{ 0x038cu, 0x038cu, 0x0040u, CanonicalizeRangeLo },
{ 0x038du, 0x038du, 0x0000u, CanonicalizeUnique },
{ 0x038eu, 0x038fu, 0x003fu, CanonicalizeRangeLo },
{ 0x0390u, 0x0390u, 0x0000u, CanonicalizeUnique },
{ 0x0391u, 0x0391u, 0x0020u, CanonicalizeRangeLo },
{ 0x0392u, 0x0392u, 0x0004u, CanonicalizeSet },
{ 0x0393u, 0x0394u, 0x0020u, CanonicalizeRangeLo },
{ 0x0395u, 0x0395u, 0x0005u, CanonicalizeSet },
{ 0x0396u, 0x0397u, 0x0020u, CanonicalizeRangeLo },
{ 0x0398u, 0x0398u, 0x0006u, CanonicalizeSet },
{ 0x0399u, 0x0399u, 0x0007u, CanonicalizeSet },
{ 0x039au, 0x039au, 0x0008u, CanonicalizeSet },
{ 0x039bu, 0x039bu, 0x0020u, CanonicalizeRangeLo },
{ 0x039cu, 0x039cu, 0x0009u, CanonicalizeSet },
{ 0x039du, 0x039fu, 0x0020u, CanonicalizeRangeLo },
{ 0x03a0u, 0x03a0u, 0x000au, CanonicalizeSet },
{ 0x03a1u, 0x03a1u, 0x000bu, CanonicalizeSet },
{ 0x03a2u, 0x03a2u, 0x0000u, CanonicalizeUnique },
{ 0x03a3u, 0x03a3u, 0x000cu, CanonicalizeSet },
{ 0x03a4u, 0x03a5u, 0x0020u, CanonicalizeRangeLo },
{ 0x03a6u, 0x03a6u, 0x000du, CanonicalizeSet },
{ 0x03a7u, 0x03abu, 0x0020u, CanonicalizeRangeLo },
{ 0x03acu, 0x03acu, 0x0026u, CanonicalizeRangeHi },
{ 0x03adu, 0x03afu, 0x0025u, CanonicalizeRangeHi },
{ 0x03b0u, 0x03b0u, 0x0000u, CanonicalizeUnique },
{ 0x03b1u, 0x03b1u, 0x0020u, CanonicalizeRangeHi },
{ 0x03b2u, 0x03b2u, 0x0004u, CanonicalizeSet },
{ 0x03b3u, 0x03b4u, 0x0020u, CanonicalizeRangeHi },
{ 0x03b5u, 0x03b5u, 0x0005u, CanonicalizeSet },
{ 0x03b6u, 0x03b7u, 0x0020u, CanonicalizeRangeHi },
{ 0x03b8u, 0x03b8u, 0x0006u, CanonicalizeSet },
{ 0x03b9u, 0x03b9u, 0x0007u, CanonicalizeSet },
{ 0x03bau, 0x03bau, 0x0008u, CanonicalizeSet },
{ 0x03bbu, 0x03bbu, 0x0020u, CanonicalizeRangeHi },
{ 0x03bcu, 0x03bcu, 0x0009u, CanonicalizeSet },
{ 0x03bdu, 0x03bfu, 0x0020u, CanonicalizeRangeHi },
{ 0x03c0u, 0x03c0u, 0x000au, CanonicalizeSet },
{ 0x03c1u, 0x03c1u, 0x000bu, CanonicalizeSet },
{ 0x03c2u, 0x03c3u, 0x000cu, CanonicalizeSet },
{ 0x03c4u, 0x03c5u, 0x0020u, CanonicalizeRangeHi },
{ 0x03c6u, 0x03c6u, 0x000du, CanonicalizeSet },
{ 0x03c7u, 0x03cbu, 0x0020u, CanonicalizeRangeHi },
{ 0x03ccu, 0x03ccu, 0x0040u, CanonicalizeRangeHi },
{ 0x03cdu, 0x03ceu, 0x003fu, CanonicalizeRangeHi },
{ 0x03cfu, 0x03cfu, 0x0008u, CanonicalizeRangeLo },
{ 0x03d0u, 0x03d0u, 0x0004u, CanonicalizeSet },
{ 0x03d1u, 0x03d1u, 0x0006u, CanonicalizeSet },
{ 0x03d2u, 0x03d4u, 0x0000u, CanonicalizeUnique },
{ 0x03d5u, 0x03d5u, 0x000du, CanonicalizeSet },
{ 0x03d6u, 0x03d6u, 0x000au, CanonicalizeSet },
{ 0x03d7u, 0x03d7u, 0x0008u, CanonicalizeRangeHi },
{ 0x03d8u, 0x03efu, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x03f0u, 0x03f0u, 0x0008u, CanonicalizeSet },
{ 0x03f1u, 0x03f1u, 0x000bu, CanonicalizeSet },
{ 0x03f2u, 0x03f2u, 0x0007u, CanonicalizeRangeLo },
{ 0x03f3u, 0x03f4u, 0x0000u, CanonicalizeUnique },
{ 0x03f5u, 0x03f5u, 0x0005u, CanonicalizeSet },
{ 0x03f6u, 0x03f6u, 0x0000u, CanonicalizeUnique },
{ 0x03f7u, 0x03f8u, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x03f9u, 0x03f9u, 0x0007u, CanonicalizeRangeHi },
{ 0x03fau, 0x03fbu, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x03fcu, 0x03fcu, 0x0000u, CanonicalizeUnique },
{ 0x03fdu, 0x03ffu, 0x0082u, CanonicalizeRangeHi },
{ 0x0400u, 0x040fu, 0x0050u, CanonicalizeRangeLo },
{ 0x0410u, 0x042fu, 0x0020u, CanonicalizeRangeLo },
{ 0x0430u, 0x044fu, 0x0020u, CanonicalizeRangeHi },
{ 0x0450u, 0x045fu, 0x0050u, CanonicalizeRangeHi },
{ 0x0460u, 0x0481u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x0482u, 0x0489u, 0x0000u, CanonicalizeUnique },
{ 0x048au, 0x04bfu, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x04c0u, 0x04c0u, 0x000fu, CanonicalizeRangeLo },
{ 0x04c1u, 0x04ceu, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x04cfu, 0x04cfu, 0x000fu, CanonicalizeRangeHi },
{ 0x04d0u, 0x0527u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x0528u, 0x0530u, 0x0000u, CanonicalizeUnique },
{ 0x0531u, 0x0556u, 0x0030u, CanonicalizeRangeLo },
{ 0x0557u, 0x0560u, 0x0000u, CanonicalizeUnique },
{ 0x0561u, 0x0586u, 0x0030u, CanonicalizeRangeHi },
{ 0x0587u, 0x109fu, 0x0000u, CanonicalizeUnique },
{ 0x10a0u, 0x10c5u, 0x1c60u, CanonicalizeRangeLo },
{ 0x10c6u, 0x1d78u, 0x0000u, CanonicalizeUnique },
{ 0x1d79u, 0x1d79u, 0x8a04u, CanonicalizeRangeLo },
{ 0x1d7au, 0x1d7cu, 0x0000u, CanonicalizeUnique },
{ 0x1d7du, 0x1d7du, 0x0ee6u, CanonicalizeRangeLo },
{ 0x1d7eu, 0x1dffu, 0x0000u, CanonicalizeUnique },
{ 0x1e00u, 0x1e5fu, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x1e60u, 0x1e61u, 0x000eu, CanonicalizeSet },
{ 0x1e62u, 0x1e95u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x1e96u, 0x1e9au, 0x0000u, CanonicalizeUnique },
{ 0x1e9bu, 0x1e9bu, 0x000eu, CanonicalizeSet },
{ 0x1e9cu, 0x1e9fu, 0x0000u, CanonicalizeUnique },
{ 0x1ea0u, 0x1effu, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x1f00u, 0x1f07u, 0x0008u, CanonicalizeRangeLo },
{ 0x1f08u, 0x1f0fu, 0x0008u, CanonicalizeRangeHi },
{ 0x1f10u, 0x1f15u, 0x0008u, CanonicalizeRangeLo },
{ 0x1f16u, 0x1f17u, 0x0000u, CanonicalizeUnique },
{ 0x1f18u, 0x1f1du, 0x0008u, CanonicalizeRangeHi },
{ 0x1f1eu, 0x1f1fu, 0x0000u, CanonicalizeUnique },
{ 0x1f20u, 0x1f27u, 0x0008u, CanonicalizeRangeLo },
{ 0x1f28u, 0x1f2fu, 0x0008u, CanonicalizeRangeHi },
{ 0x1f30u, 0x1f37u, 0x0008u, CanonicalizeRangeLo },
{ 0x1f38u, 0x1f3fu, 0x0008u, CanonicalizeRangeHi },
{ 0x1f40u, 0x1f45u, 0x0008u, CanonicalizeRangeLo },
{ 0x1f46u, 0x1f47u, 0x0000u, CanonicalizeUnique },
{ 0x1f48u, 0x1f4du, 0x0008u, CanonicalizeRangeHi },
{ 0x1f4eu, 0x1f50u, 0x0000u, CanonicalizeUnique },
{ 0x1f51u, 0x1f51u, 0x0008u, CanonicalizeRangeLo },
{ 0x1f52u, 0x1f52u, 0x0000u, CanonicalizeUnique },
{ 0x1f53u, 0x1f53u, 0x0008u, CanonicalizeRangeLo },
{ 0x1f54u, 0x1f54u, 0x0000u, CanonicalizeUnique },
{ 0x1f55u, 0x1f55u, 0x0008u, CanonicalizeRangeLo },
{ 0x1f56u, 0x1f56u, 0x0000u, CanonicalizeUnique },
{ 0x1f57u, 0x1f57u, 0x0008u, CanonicalizeRangeLo },
{ 0x1f58u, 0x1f58u, 0x0000u, CanonicalizeUnique },
{ 0x1f59u, 0x1f59u, 0x0008u, CanonicalizeRangeHi },
{ 0x1f5au, 0x1f5au, 0x0000u, CanonicalizeUnique },
{ 0x1f5bu, 0x1f5bu, 0x0008u, CanonicalizeRangeHi },
{ 0x1f5cu, 0x1f5cu, 0x0000u, CanonicalizeUnique },
{ 0x1f5du, 0x1f5du, 0x0008u, CanonicalizeRangeHi },
{ 0x1f5eu, 0x1f5eu, 0x0000u, CanonicalizeUnique },
{ 0x1f5fu, 0x1f5fu, 0x0008u, CanonicalizeRangeHi },
{ 0x1f60u, 0x1f67u, 0x0008u, CanonicalizeRangeLo },
{ 0x1f68u, 0x1f6fu, 0x0008u, CanonicalizeRangeHi },
{ 0x1f70u, 0x1f71u, 0x004au, CanonicalizeRangeLo },
{ 0x1f72u, 0x1f75u, 0x0056u, CanonicalizeRangeLo },
{ 0x1f76u, 0x1f77u, 0x0064u, CanonicalizeRangeLo },
{ 0x1f78u, 0x1f79u, 0x0080u, CanonicalizeRangeLo },
{ 0x1f7au, 0x1f7bu, 0x0070u, CanonicalizeRangeLo },
{ 0x1f7cu, 0x1f7du, 0x007eu, CanonicalizeRangeLo },
{ 0x1f7eu, 0x1fafu, 0x0000u, CanonicalizeUnique },
{ 0x1fb0u, 0x1fb1u, 0x0008u, CanonicalizeRangeLo },
{ 0x1fb2u, 0x1fb7u, 0x0000u, CanonicalizeUnique },
{ 0x1fb8u, 0x1fb9u, 0x0008u, CanonicalizeRangeHi },
{ 0x1fbau, 0x1fbbu, 0x004au, CanonicalizeRangeHi },
{ 0x1fbcu, 0x1fbdu, 0x0000u, CanonicalizeUnique },
{ 0x1fbeu, 0x1fbeu, 0x0007u, CanonicalizeSet },
{ 0x1fbfu, 0x1fc7u, 0x0000u, CanonicalizeUnique },
{ 0x1fc8u, 0x1fcbu, 0x0056u, CanonicalizeRangeHi },
{ 0x1fccu, 0x1fcfu, 0x0000u, CanonicalizeUnique },
{ 0x1fd0u, 0x1fd1u, 0x0008u, CanonicalizeRangeLo },
{ 0x1fd2u, 0x1fd7u, 0x0000u, CanonicalizeUnique },
{ 0x1fd8u, 0x1fd9u, 0x0008u, CanonicalizeRangeHi },
{ 0x1fdau, 0x1fdbu, 0x0064u, CanonicalizeRangeHi },
{ 0x1fdcu, 0x1fdfu, 0x0000u, CanonicalizeUnique },
{ 0x1fe0u, 0x1fe1u, 0x0008u, CanonicalizeRangeLo },
{ 0x1fe2u, 0x1fe4u, 0x0000u, CanonicalizeUnique },
{ 0x1fe5u, 0x1fe5u, 0x0007u, CanonicalizeRangeLo },
{ 0x1fe6u, 0x1fe7u, 0x0000u, CanonicalizeUnique },
{ 0x1fe8u, 0x1fe9u, 0x0008u, CanonicalizeRangeHi },
{ 0x1feau, 0x1febu, 0x0070u, CanonicalizeRangeHi },
{ 0x1fecu, 0x1fecu, 0x0007u, CanonicalizeRangeHi },
{ 0x1fedu, 0x1ff7u, 0x0000u, CanonicalizeUnique },
{ 0x1ff8u, 0x1ff9u, 0x0080u, CanonicalizeRangeHi },
{ 0x1ffau, 0x1ffbu, 0x007eu, CanonicalizeRangeHi },
{ 0x1ffcu, 0x2131u, 0x0000u, CanonicalizeUnique },
{ 0x2132u, 0x2132u, 0x001cu, CanonicalizeRangeLo },
{ 0x2133u, 0x214du, 0x0000u, CanonicalizeUnique },
{ 0x214eu, 0x214eu, 0x001cu, CanonicalizeRangeHi },
{ 0x214fu, 0x215fu, 0x0000u, CanonicalizeUnique },
{ 0x2160u, 0x216fu, 0x0010u, CanonicalizeRangeLo },
{ 0x2170u, 0x217fu, 0x0010u, CanonicalizeRangeHi },
{ 0x2180u, 0x2182u, 0x0000u, CanonicalizeUnique },
{ 0x2183u, 0x2184u, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x2185u, 0x24b5u, 0x0000u, CanonicalizeUnique },
{ 0x24b6u, 0x24cfu, 0x001au, CanonicalizeRangeLo },
{ 0x24d0u, 0x24e9u, 0x001au, CanonicalizeRangeHi },
{ 0x24eau, 0x2bffu, 0x0000u, CanonicalizeUnique },
{ 0x2c00u, 0x2c2eu, 0x0030u, CanonicalizeRangeLo },
{ 0x2c2fu, 0x2c2fu, 0x0000u, CanonicalizeUnique },
{ 0x2c30u, 0x2c5eu, 0x0030u, CanonicalizeRangeHi },
{ 0x2c5fu, 0x2c5fu, 0x0000u, CanonicalizeUnique },
{ 0x2c60u, 0x2c61u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x2c62u, 0x2c62u, 0x29f7u, CanonicalizeRangeHi },
{ 0x2c63u, 0x2c63u, 0x0ee6u, CanonicalizeRangeHi },
{ 0x2c64u, 0x2c64u, 0x29e7u, CanonicalizeRangeHi },
{ 0x2c65u, 0x2c65u, 0x2a2bu, CanonicalizeRangeHi },
{ 0x2c66u, 0x2c66u, 0x2a28u, CanonicalizeRangeHi },
{ 0x2c67u, 0x2c6cu, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x2c6du, 0x2c6du, 0x2a1cu, CanonicalizeRangeHi },
{ 0x2c6eu, 0x2c6eu, 0x29fdu, CanonicalizeRangeHi },
{ 0x2c6fu, 0x2c6fu, 0x2a1fu, CanonicalizeRangeHi },
{ 0x2c70u, 0x2c70u, 0x2a1eu, CanonicalizeRangeHi },
{ 0x2c71u, 0x2c71u, 0x0000u, CanonicalizeUnique },
{ 0x2c72u, 0x2c73u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x2c74u, 0x2c74u, 0x0000u, CanonicalizeUnique },
{ 0x2c75u, 0x2c76u, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x2c77u, 0x2c7du, 0x0000u, CanonicalizeUnique },
{ 0x2c7eu, 0x2c7fu, 0x2a3fu, CanonicalizeRangeHi },
{ 0x2c80u, 0x2ce3u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0x2ce4u, 0x2ceau, 0x0000u, CanonicalizeUnique },
{ 0x2cebu, 0x2ceeu, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0x2cefu, 0x2cffu, 0x0000u, CanonicalizeUnique },
{ 0x2d00u, 0x2d25u, 0x1c60u, CanonicalizeRangeHi },
{ 0x2d26u, 0xa63fu, 0x0000u, CanonicalizeUnique },
{ 0xa640u, 0xa66du, 0x0000u, CanonicalizeAlternatingAligned },
{ 0xa66eu, 0xa67fu, 0x0000u, CanonicalizeUnique },
{ 0xa680u, 0xa697u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0xa698u, 0xa721u, 0x0000u, CanonicalizeUnique },
{ 0xa722u, 0xa72fu, 0x0000u, CanonicalizeAlternatingAligned },
{ 0xa730u, 0xa731u, 0x0000u, CanonicalizeUnique },
{ 0xa732u, 0xa76fu, 0x0000u, CanonicalizeAlternatingAligned },
{ 0xa770u, 0xa778u, 0x0000u, CanonicalizeUnique },
{ 0xa779u, 0xa77cu, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0xa77du, 0xa77du, 0x8a04u, CanonicalizeRangeHi },
{ 0xa77eu, 0xa787u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0xa788u, 0xa78au, 0x0000u, CanonicalizeUnique },
{ 0xa78bu, 0xa78cu, 0x0000u, CanonicalizeAlternatingUnaligned },
{ 0xa78du, 0xa78du, 0xa528u, CanonicalizeRangeHi },
{ 0xa78eu, 0xa78fu, 0x0000u, CanonicalizeUnique },
{ 0xa790u, 0xa791u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0xa792u, 0xa79fu, 0x0000u, CanonicalizeUnique },
{ 0xa7a0u, 0xa7a9u, 0x0000u, CanonicalizeAlternatingAligned },
{ 0xa7aau, 0xff20u, 0x0000u, CanonicalizeUnique },
{ 0xff21u, 0xff3au, 0x0020u, CanonicalizeRangeLo },
{ 0xff3bu, 0xff40u, 0x0000u, CanonicalizeUnique },
{ 0xff41u, 0xff5au, 0x0020u, CanonicalizeRangeHi },
{ 0xff5bu, 0xffffu, 0x0000u, CanonicalizeUnique },
};
const size_t LATIN_CANONICALIZATION_RANGES = 20;
LatinCanonicalizationRange latinRangeInfo[LATIN_CANONICALIZATION_RANGES] = {
{ 0x0000u, 0x0040u, 0x0000u, CanonicalizeLatinSelf },
{ 0x0041u, 0x005au, 0x0000u, CanonicalizeLatinMask0x20 },
{ 0x005bu, 0x0060u, 0x0000u, CanonicalizeLatinSelf },
{ 0x0061u, 0x007au, 0x0000u, CanonicalizeLatinMask0x20 },
{ 0x007bu, 0x00bfu, 0x0000u, CanonicalizeLatinSelf },
{ 0x00c0u, 0x00d6u, 0x0000u, CanonicalizeLatinMask0x20 },
{ 0x00d7u, 0x00d7u, 0x0000u, CanonicalizeLatinSelf },
{ 0x00d8u, 0x00deu, 0x0000u, CanonicalizeLatinMask0x20 },
{ 0x00dfu, 0x00dfu, 0x0000u, CanonicalizeLatinSelf },
{ 0x00e0u, 0x00f6u, 0x0000u, CanonicalizeLatinMask0x20 },
{ 0x00f7u, 0x00f7u, 0x0000u, CanonicalizeLatinSelf },
{ 0x00f8u, 0x00feu, 0x0000u, CanonicalizeLatinMask0x20 },
{ 0x00ffu, 0x00ffu, 0x0000u, CanonicalizeLatinSelf },
{ 0x0100u, 0x0177u, 0x0000u, CanonicalizeLatinInvalid },
{ 0x0178u, 0x0178u, 0x00ffu, CanonicalizeLatinOther },
{ 0x0179u, 0x039bu, 0x0000u, CanonicalizeLatinInvalid },
{ 0x039cu, 0x039cu, 0x00b5u, CanonicalizeLatinOther },
{ 0x039du, 0x03bbu, 0x0000u, CanonicalizeLatinInvalid },
{ 0x03bcu, 0x03bcu, 0x00b5u, CanonicalizeLatinOther },
{ 0x03bdu, 0xffffu, 0x0000u, CanonicalizeLatinInvalid },
};
} } // JSC::Yarr

Просмотреть файл

@ -0,0 +1,139 @@
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef YarrCanonicalizeUCS2_H
#define YarrCanonicalizeUCS2_H
#include <stdint.h>
#include "wtfbridge.h"
#include "assembler/wtf/Assertions.h"
namespace JSC { namespace Yarr {
// This set of data (autogenerated using YarrCanonicalizeUCS2.js into YarrCanonicalizeUCS2.cpp)
// provides information for each UCS2 code point as to the set of code points that it should
// match under the ES5.1 case insensitive RegExp matching rules, specified in 15.10.2.8.
enum UCS2CanonicalizationType {
CanonicalizeUnique, // No canonically equal values, e.g. 0x0.
CanonicalizeSet, // Value indicates a set in characterSetInfo.
CanonicalizeRangeLo, // Value is positive delta to pair, E.g. 0x41 has value 0x20, -> 0x61.
CanonicalizeRangeHi, // Value is positive delta to pair, E.g. 0x61 has value 0x20, -> 0x41.
CanonicalizeAlternatingAligned, // Aligned consequtive pair, e.g. 0x1f4,0x1f5.
CanonicalizeAlternatingUnaligned // Unaligned consequtive pair, e.g. 0x241,0x242.
};
struct UCS2CanonicalizationRange { uint16_t begin, end, value, type; };
extern const size_t UCS2_CANONICALIZATION_RANGES;
extern uint16_t* characterSetInfo[];
extern UCS2CanonicalizationRange rangeInfo[];
// This table is similar to the full rangeInfo table, however this maps from UCS2 codepoints to
// the set of Latin1 codepoints that could match.
enum LatinCanonicalizationType {
CanonicalizeLatinSelf, // This character is in the Latin1 range, but has no canonical equivalent in the range.
CanonicalizeLatinMask0x20, // One of a pair of characters, under the mask 0x20.
CanonicalizeLatinOther, // This character is not in the Latin1 range, but canonicalizes to another that is.
CanonicalizeLatinInvalid // Cannot match against Latin1 input.
};
struct LatinCanonicalizationRange { uint16_t begin, end, value, type; };
extern const size_t LATIN_CANONICALIZATION_RANGES;
extern LatinCanonicalizationRange latinRangeInfo[];
// This searches in log2 time over ~364 entries, so should typically result in 8 compares.
inline UCS2CanonicalizationRange* rangeInfoFor(UChar ch)
{
UCS2CanonicalizationRange* info = rangeInfo;
size_t entries = UCS2_CANONICALIZATION_RANGES;
while (true) {
size_t candidate = entries >> 1;
UCS2CanonicalizationRange* candidateInfo = info + candidate;
if (ch < candidateInfo->begin)
entries = candidate;
else if (ch <= candidateInfo->end)
return candidateInfo;
else {
info = candidateInfo + 1;
entries -= (candidate + 1);
}
}
}
// Should only be called for characters that have one canonically matching value.
inline UChar getCanonicalPair(UCS2CanonicalizationRange* info, UChar ch)
{
ASSERT(ch >= info->begin && ch <= info->end);
switch (info->type) {
case CanonicalizeRangeLo:
return ch + info->value;
case CanonicalizeRangeHi:
return ch - info->value;
case CanonicalizeAlternatingAligned:
return ch ^ 1;
case CanonicalizeAlternatingUnaligned:
return ((ch - 1) ^ 1) + 1;
default:
ASSERT_NOT_REACHED();
}
ASSERT_NOT_REACHED();
return 0;
}
// Returns true if no other UCS2 codepoint can match this value.
inline bool isCanonicallyUnique(UChar ch)
{
return rangeInfoFor(ch)->type == CanonicalizeUnique;
}
// Returns true if values are equal, under the canonicalization rules.
inline bool areCanonicallyEquivalent(UChar a, UChar b)
{
UCS2CanonicalizationRange* info = rangeInfoFor(a);
switch (info->type) {
case CanonicalizeUnique:
return a == b;
case CanonicalizeSet: {
for (uint16_t* set = characterSetInfo[info->value]; (a = *set); ++set) {
if (a == b)
return true;
}
return false;
}
case CanonicalizeRangeLo:
return (a == b) || (a + info->value == b);
case CanonicalizeRangeHi:
return (a == b) || (a - info->value == b);
case CanonicalizeAlternatingAligned:
return (a | 1) == (b | 1);
case CanonicalizeAlternatingUnaligned:
return ((a - 1) | 1) == ((b - 1) | 1);
}
ASSERT_NOT_REACHED();
return false;
}
} } // JSC::Yarr
#endif

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше