Browse Source

Finish V8 update

v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
a49bf8622f
  1. 1
      deps/v8/SConstruct
  2. 1089
      deps/v8/src/date-delay.js
  3. 2130
      deps/v8/src/debug-delay.js
  4. 268
      deps/v8/src/json-delay.js
  5. 431
      deps/v8/src/liveedit-delay.js
  6. 2369
      deps/v8/src/mirror-delay.js
  7. 190
      deps/v8/src/number-info.h
  8. 497
      deps/v8/src/regexp-delay.js

1
deps/v8/SConstruct

@ -275,7 +275,6 @@ V8_EXTRA_FLAGS = {
'gcc': {
'all': {
'WARNINGFLAGS': ['-Wall',
'-Werror',
'-W',
'-Wno-unused-parameter',
'-Wnon-virtual-dtor']

1089
deps/v8/src/date-delay.js

File diff suppressed because it is too large

2130
deps/v8/src/debug-delay.js

File diff suppressed because it is too large

268
deps/v8/src/json-delay.js

@ -1,268 +0,0 @@
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 THE COPYRIGHT
// OWNER 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.
var $JSON = global.JSON;
function ParseJSONUnfiltered(text) {
var s = $String(text);
var f = %CompileString(text, true);
return f();
}
function Revive(holder, name, reviver) {
var val = holder[name];
if (IS_OBJECT(val)) {
if (IS_ARRAY(val)) {
var length = val.length;
for (var i = 0; i < length; i++) {
var newElement = Revive(val, $String(i), reviver);
val[i] = newElement;
}
} else {
for (var p in val) {
if (ObjectHasOwnProperty.call(val, p)) {
var newElement = Revive(val, p, reviver);
if (IS_UNDEFINED(newElement)) {
delete val[p];
} else {
val[p] = newElement;
}
}
}
}
}
return reviver.call(holder, name, val);
}
function JSONParse(text, reviver) {
var unfiltered = ParseJSONUnfiltered(text);
if (IS_FUNCTION(reviver)) {
return Revive({'': unfiltered}, '', reviver);
} else {
return unfiltered;
}
}
var characterQuoteCache = {
'\"': '\\"',
'\\': '\\\\',
'/': '\\/',
'\b': '\\b',
'\f': '\\f',
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
'\x0B': '\\u000b'
};
function QuoteSingleJSONCharacter(c) {
if (c in characterQuoteCache) {
return characterQuoteCache[c];
}
var charCode = c.charCodeAt(0);
var result;
if (charCode < 16) result = '\\u000';
else if (charCode < 256) result = '\\u00';
else if (charCode < 4096) result = '\\u0';
else result = '\\u';
result += charCode.toString(16);
characterQuoteCache[c] = result;
return result;
}
function QuoteJSONString(str) {
var quotable = /[\\\"\x00-\x1f\x80-\uffff]/g;
return '"' + str.replace(quotable, QuoteSingleJSONCharacter) + '"';
}
function StackContains(stack, val) {
var length = stack.length;
for (var i = 0; i < length; i++) {
if (stack[i] === val) {
return true;
}
}
return false;
}
function SerializeArray(value, replacer, stack, indent, gap) {
if (StackContains(stack, value)) {
throw MakeTypeError('circular_structure', []);
}
stack.push(value);
var stepback = indent;
indent += gap;
var partial = [];
var len = value.length;
for (var i = 0; i < len; i++) {
var strP = JSONSerialize($String(i), value, replacer, stack,
indent, gap);
if (IS_UNDEFINED(strP)) {
strP = "null";
}
partial.push(strP);
}
var final;
if (gap == "") {
final = "[" + partial.join(",") + "]";
} else if (partial.length > 0) {
var separator = ",\n" + indent;
final = "[\n" + indent + partial.join(separator) + "\n" +
stepback + "]";
} else {
final = "[]";
}
stack.pop();
return final;
}
function SerializeObject(value, replacer, stack, indent, gap) {
if (StackContains(stack, value)) {
throw MakeTypeError('circular_structure', []);
}
stack.push(value);
var stepback = indent;
indent += gap;
var partial = [];
if (IS_ARRAY(replacer)) {
var length = replacer.length;
for (var i = 0; i < length; i++) {
if (ObjectHasOwnProperty.call(replacer, i)) {
var p = replacer[i];
var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
if (!IS_UNDEFINED(strP)) {
var member = QuoteJSONString(p) + ":";
if (gap != "") member += " ";
member += strP;
partial.push(member);
}
}
}
} else {
for (var p in value) {
if (ObjectHasOwnProperty.call(value, p)) {
var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
if (!IS_UNDEFINED(strP)) {
var member = QuoteJSONString(p) + ":";
if (gap != "") member += " ";
member += strP;
partial.push(member);
}
}
}
}
var final;
if (gap == "") {
final = "{" + partial.join(",") + "}";
} else if (partial.length > 0) {
var separator = ",\n" + indent;
final = "{\n" + indent + partial.join(separator) + "\n" +
stepback + "}";
} else {
final = "{}";
}
stack.pop();
return final;
}
function JSONSerialize(key, holder, replacer, stack, indent, gap) {
var value = holder[key];
if (IS_OBJECT(value) && value) {
var toJSON = value.toJSON;
if (IS_FUNCTION(toJSON)) {
value = toJSON.call(value, key);
}
}
if (IS_FUNCTION(replacer)) {
value = replacer.call(holder, key, value);
}
// Unwrap value if necessary
if (IS_OBJECT(value)) {
if (IS_NUMBER_WRAPPER(value)) {
value = $Number(value);
} else if (IS_STRING_WRAPPER(value)) {
value = $String(value);
} else if (IS_BOOLEAN_WRAPPER(value)) {
value = $Boolean(value);
}
}
switch (typeof value) {
case "string":
return QuoteJSONString(value);
case "object":
if (!value) {
return "null";
} else if (IS_ARRAY(value)) {
return SerializeArray(value, replacer, stack, indent, gap);
} else {
return SerializeObject(value, replacer, stack, indent, gap);
}
case "number":
return $isFinite(value) ? $String(value) : "null";
case "boolean":
return value ? "true" : "false";
}
}
function JSONStringify(value, replacer, space) {
var stack = [];
var indent = "";
if (IS_OBJECT(space)) {
// Unwrap 'space' if it is wrapped
if (IS_NUMBER_WRAPPER(space)) {
space = $Number(space);
} else if (IS_STRING_WRAPPER(space)) {
space = $String(space);
}
}
var gap;
if (IS_NUMBER(space)) {
space = $Math.min(space, 10);
gap = "";
for (var i = 0; i < space; i++) {
gap += " ";
}
} else if (IS_STRING(space)) {
if (space.length > 10) {
gap = space.substring(0, 10);
} else {
gap = space;
}
} else {
gap = "";
}
return JSONSerialize('', {'': value}, replacer, stack, indent, gap);
}
function SetupJSON() {
InstallFunctions($JSON, DONT_ENUM, $Array(
"parse", JSONParse,
"stringify", JSONStringify
));
}
SetupJSON();

431
deps/v8/src/liveedit-delay.js

@ -1,431 +0,0 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 THE COPYRIGHT
// OWNER 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.
// LiveEdit feature implementation. The script should be executed after
// debug-delay.js.
// Changes script text and recompiles all relevant functions if possible.
// The change is always a substring (change_pos, change_pos + change_len)
// being replaced with a completely different string new_str.
//
// Only one function will have its Code changed in result of this function.
// All nested functions (should they have any instances at the moment) are left
// unchanged and re-linked to a newly created script instance representing old
// version of the source. (Generally speaking,
// during the change all nested functions are erased and completely different
// set of nested functions are introduced.) All other functions just have
// their positions updated.
//
// @param {Script} script that is being changed
// @param {Array} change_log a list that collects engineer-readable description
// of what happened.
Debug.LiveEditChangeScript = function(script, change_pos, change_len, new_str,
change_log) {
// So far the function works as namespace.
var liveedit = Debug.LiveEditChangeScript;
var Assert = liveedit.Assert;
// Fully compiles source string as a script. Returns Array of
// FunctionCompileInfo -- a descriptions of all functions of the script.
// Elements of array are ordered by start positions of functions (from top
// to bottom) in the source. Fields outer_index and next_sibling_index help
// to navigate the nesting structure of functions.
//
// The script is used for compilation, because it produces code that
// needs to be linked with some particular script (for nested functions).
function DebugGatherCompileInfo(source) {
// Get function info, elements are partially sorted (it is a tree
// of nested functions serialized as parent followed by serialized children.
var raw_compile_info = %LiveEditGatherCompileInfo(script, source);
// Sort function infos by start position field.
var compile_info = new Array();
var old_index_map = new Array();
for (var i = 0; i < raw_compile_info.length; i++) {
compile_info.push(new liveedit.FunctionCompileInfo(raw_compile_info[i]));
old_index_map.push(i);
}
for (var i = 0; i < compile_info.length; i++) {
var k = i;
for (var j = i + 1; j < compile_info.length; j++) {
if (compile_info[k].start_position > compile_info[j].start_position) {
k = j;
}
}
if (k != i) {
var temp_info = compile_info[k];
var temp_index = old_index_map[k];
compile_info[k] = compile_info[i];
old_index_map[k] = old_index_map[i];
compile_info[i] = temp_info;
old_index_map[i] = temp_index;
}
}
// After sorting update outer_inder field using old_index_map. Also
// set next_sibling_index field.
var current_index = 0;
// The recursive function, that goes over all children of a particular
// node (i.e. function info).
function ResetIndexes(new_parent_index, old_parent_index) {
var previous_sibling = -1;
while (current_index < compile_info.length &&
compile_info[current_index].outer_index == old_parent_index) {
var saved_index = current_index;
compile_info[saved_index].outer_index = new_parent_index;
if (previous_sibling != -1) {
compile_info[previous_sibling].next_sibling_index = saved_index;
}
previous_sibling = saved_index;
current_index++;
ResetIndexes(saved_index, old_index_map[saved_index]);
}
if (previous_sibling != -1) {
compile_info[previous_sibling].next_sibling_index = -1;
}
}
ResetIndexes(-1, -1);
Assert(current_index == compile_info.length);
return compile_info;
}
// Given a positions, finds a function that fully includes the entire change.
function FindChangedFunction(compile_info, offset, len) {
// First condition: function should start before the change region.
// Function #0 (whole-script function) always does, but we want
// one, that is later in this list.
var index = 0;
while (index + 1 < compile_info.length &&
compile_info[index + 1].start_position <= offset) {
index++;
}
// Now we are at the last function that begins before the change
// region. The function that covers entire change region is either
// this function or the enclosing one.
for (; compile_info[index].end_position < offset + len;
index = compile_info[index].outer_index) {
Assert(index != -1);
}
return index;
}
// Variable forward declarations. Preprocessor "Minifier" needs them.
var old_compile_info;
var shared_infos;
// Finds SharedFunctionInfo that corresponds compile info with index
// in old version of the script.
function FindFunctionInfo(index) {
var old_info = old_compile_info[index];
for (var i = 0; i < shared_infos.length; i++) {
var info = shared_infos[i];
if (info.start_position == old_info.start_position &&
info.end_position == old_info.end_position) {
return info;
}
}
}
// Replaces function's Code.
function PatchCode(new_info, shared_info) {
%LiveEditReplaceFunctionCode(new_info.raw_array, shared_info.raw_array);
change_log.push( {function_patched: new_info.function_name} );
}
var change_len_old;
var change_len_new;
// Translate position in old version of script into position in new
// version of script.
function PosTranslator(old_pos) {
if (old_pos <= change_pos) {
return old_pos;
}
if (old_pos >= change_pos + change_len_old) {
return old_pos + change_len_new - change_len_old;
}
return -1;
}
var position_change_array;
var position_patch_report;
function PatchPositions(new_info, shared_info) {
if (!shared_info) {
// TODO: explain what is happening.
return;
}
%LiveEditPatchFunctionPositions(shared_info.raw_array,
position_change_array);
position_patch_report.push( { name: new_info.function_name } );
}
var link_to_old_script_report;
var old_script;
// Makes a function associated with another instance of a script (the
// one representing its old version). This way the function still
// may access its own text.
function LinkToOldScript(shared_info) {
%LiveEditRelinkFunctionToScript(shared_info.raw_array, old_script);
link_to_old_script_report.push( { name: shared_info.function_name } );
}
var old_source = script.source;
var change_len_old = change_len;
var change_len_new = new_str.length;
// Prepare new source string.
var new_source = old_source.substring(0, change_pos) +
new_str + old_source.substring(change_pos + change_len);
// Find all SharedFunctionInfo's that are compiled from this script.
var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script);
var shared_infos = new Array();
for (var i = 0; i < shared_raw_list.length; i++) {
shared_infos.push(new liveedit.SharedInfoWrapper(shared_raw_list[i]));
}
// Gather compile information about old version of script.
var old_compile_info = DebugGatherCompileInfo(old_source);
// Gather compile information about new version of script.
var new_compile_info;
try {
new_compile_info = DebugGatherCompileInfo(new_source);
} catch (e) {
throw new liveedit.Failure("Failed to compile new version of script: " + e);
}
// An index of a single function, that is going to have its code replaced.
var function_being_patched =
FindChangedFunction(old_compile_info, change_pos, change_len_old);
// In old and new script versions function with a change should have the
// same indexes.
var function_being_patched2 =
FindChangedFunction(new_compile_info, change_pos, change_len_new);
Assert(function_being_patched == function_being_patched2,
"inconsistent old/new compile info");
// Check that function being patched has the same expectations in a new
// version. Otherwise we cannot safely patch its behavior and should
// choose the outer function instead.
while (!liveedit.CompareFunctionExpectations(
old_compile_info[function_being_patched],
new_compile_info[function_being_patched])) {
Assert(old_compile_info[function_being_patched].outer_index ==
new_compile_info[function_being_patched].outer_index);
function_being_patched =
old_compile_info[function_being_patched].outer_index;
Assert(function_being_patched != -1);
}
// Check that function being patched is not currently on stack.
liveedit.CheckStackActivations(
[ FindFunctionInfo(function_being_patched) ], change_log );
// Committing all changes.
var old_script_name = liveedit.CreateNameForOldScript(script);
// Update the script text and create a new script representing an old
// version of the script.
var old_script = %LiveEditReplaceScript(script, new_source, old_script_name);
PatchCode(new_compile_info[function_being_patched],
FindFunctionInfo(function_being_patched));
var position_patch_report = new Array();
change_log.push( {position_patched: position_patch_report} );
var position_change_array = [ change_pos,
change_pos + change_len_old,
change_pos + change_len_new ];
// Update positions of all outer functions (i.e. all functions, that
// are partially below the function being patched).
for (var i = new_compile_info[function_being_patched].outer_index;
i != -1;
i = new_compile_info[i].outer_index) {
PatchPositions(new_compile_info[i], FindFunctionInfo(i));
}
// Update positions of all functions that are fully below the function
// being patched.
var old_next_sibling =
old_compile_info[function_being_patched].next_sibling_index;
var new_next_sibling =
new_compile_info[function_being_patched].next_sibling_index;
// We simply go over the tail of both old and new lists. Their tails should
// have an identical structure.
if (old_next_sibling == -1) {
Assert(new_next_sibling == -1);
} else {
Assert(old_compile_info.length - old_next_sibling ==
new_compile_info.length - new_next_sibling);
for (var i = old_next_sibling, j = new_next_sibling;
i < old_compile_info.length; i++, j++) {
PatchPositions(new_compile_info[j], FindFunctionInfo(i));
}
}
var link_to_old_script_report = new Array();
change_log.push( { linked_to_old_script: link_to_old_script_report } );
// We need to link to old script all former nested functions.
for (var i = function_being_patched + 1; i < old_next_sibling; i++) {
LinkToOldScript(FindFunctionInfo(i), old_script);
}
}
Debug.LiveEditChangeScript.Assert = function(condition, message) {
if (!condition) {
if (message) {
throw "Assert " + message;
} else {
throw "Assert";
}
}
}
// An object describing function compilation details. Its index fields
// apply to indexes inside array that stores these objects.
Debug.LiveEditChangeScript.FunctionCompileInfo = function(raw_array) {
this.function_name = raw_array[0];
this.start_position = raw_array[1];
this.end_position = raw_array[2];
this.param_num = raw_array[3];
this.code = raw_array[4];
this.scope_info = raw_array[5];
this.outer_index = raw_array[6];
this.next_sibling_index = null;
this.raw_array = raw_array;
}
// A structure describing SharedFunctionInfo.
Debug.LiveEditChangeScript.SharedInfoWrapper = function(raw_array) {
this.function_name = raw_array[0];
this.start_position = raw_array[1];
this.end_position = raw_array[2];
this.info = raw_array[3];
this.raw_array = raw_array;
}
// Adds a suffix to script name to mark that it is old version.
Debug.LiveEditChangeScript.CreateNameForOldScript = function(script) {
// TODO(635): try better than this; support several changes.
return script.name + " (old)";
}
// Compares a function interface old and new version, whether it
// changed or not.
Debug.LiveEditChangeScript.CompareFunctionExpectations =
function(function_info1, function_info2) {
// Check that function has the same number of parameters (there may exist
// an adapter, that won't survive function parameter number change).
if (function_info1.param_num != function_info2.param_num) {
return false;
}
var scope_info1 = function_info1.scope_info;
var scope_info2 = function_info2.scope_info;
if (!scope_info1) {
return !scope_info2;
}
if (scope_info1.length != scope_info2.length) {
return false;
}
// Check that outer scope structure is not changed. Otherwise the function
// will not properly work with existing scopes.
return scope_info1.toString() == scope_info2.toString();
}
// For array of wrapped shared function infos checks that none of them
// have activations on stack (of any thread). Throws a Failure exception
// if this proves to be false.
Debug.LiveEditChangeScript.CheckStackActivations = function(shared_wrapper_list,
change_log) {
var liveedit = Debug.LiveEditChangeScript;
var shared_list = new Array();
for (var i = 0; i < shared_wrapper_list.length; i++) {
shared_list[i] = shared_wrapper_list[i].info;
}
var result = %LiveEditCheckStackActivations(shared_list);
var problems = new Array();
for (var i = 0; i < shared_list.length; i++) {
if (result[i] == liveedit.FunctionPatchabilityStatus.FUNCTION_BLOCKED_ON_STACK) {
var shared = shared_list[i];
var description = {
name: shared.function_name,
start_pos: shared.start_position,
end_pos: shared.end_position
};
problems.push(description);
}
}
if (problems.length > 0) {
change_log.push( { functions_on_stack: problems } );
throw new liveedit.Failure("Blocked by functions on stack");
}
}
// A copy of the FunctionPatchabilityStatus enum from liveedit.h
Debug.LiveEditChangeScript.FunctionPatchabilityStatus = {
FUNCTION_AVAILABLE_FOR_PATCH: 0,
FUNCTION_BLOCKED_ON_STACK: 1
}
// A logical failure in liveedit process. This means that change_log
// is valid and consistent description of what happened.
Debug.LiveEditChangeScript.Failure = function(message) {
this.message = message;
}
Debug.LiveEditChangeScript.Failure.prototype.toString = function() {
return "LiveEdit Failure: " + this.message;
}
// A testing entry.
Debug.LiveEditChangeScript.GetPcFromSourcePos = function(func, source_pos) {
return %GetFunctionCodePositionFromSource(func, source_pos);
}

2369
deps/v8/src/mirror-delay.js

File diff suppressed because it is too large

190
deps/v8/src/number-info.h

@ -1,190 +0,0 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 THE COPYRIGHT
// OWNER 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 V8_NUMBER_INFO_H_
#define V8_NUMBER_INFO_H_
namespace v8 {
namespace internal {
// Unknown
// |
// Number
// / |
// HeapNumber Integer32
// | |
// | Smi
// | /
// Uninitialized.
class NumberInfo {
public:
NumberInfo() { }
static inline NumberInfo Unknown();
// We know it's a number of some sort.
static inline NumberInfo Number();
// We know it's signed or unsigned 32 bit integer.
static inline NumberInfo Integer32();
// We know it's a Smi.
static inline NumberInfo Smi();
// We know it's a heap number.
static inline NumberInfo HeapNumber();
// We haven't started collecting info yet.
static inline NumberInfo Uninitialized();
// Return compact representation. Very sensitive to enum values below!
int ThreeBitRepresentation() {
ASSERT(type_ != kUninitializedType);
int answer = type_ > 6 ? type_ -2 : type_;
ASSERT(answer >= 0);
ASSERT(answer <= 7);
return answer;
}
// Decode compact representation. Very sensitive to enum values below!
static NumberInfo ExpandedRepresentation(int three_bit_representation) {
Type t = static_cast<Type>(three_bit_representation >= 6 ?
three_bit_representation + 2 :
three_bit_representation);
ASSERT(t == kUnknownType ||
t == kNumberType ||
t == kInteger32Type ||
t == kSmiType ||
t == kHeapNumberType);
return NumberInfo(t);
}
int ToInt() {
return type_;
}
static NumberInfo FromInt(int bit_representation) {
Type t = static_cast<Type>(bit_representation);
ASSERT(t == kUnknownType ||
t == kNumberType ||
t == kInteger32Type ||
t == kSmiType ||
t == kHeapNumberType);
return NumberInfo(t);
}
// Return the weakest (least precise) common type.
static NumberInfo Combine(NumberInfo a, NumberInfo b) {
return NumberInfo(static_cast<Type>(a.type_ & b.type_));
}
inline bool IsUnknown() {
return type_ == kUnknownType;
}
inline bool IsNumber() {
ASSERT(type_ != kUninitializedType);
return ((type_ & kNumberType) == kNumberType);
}
inline bool IsSmi() {
ASSERT(type_ != kUninitializedType);
return ((type_ & kSmiType) == kSmiType);
}
inline bool IsInteger32() {
ASSERT(type_ != kUninitializedType);
return ((type_ & kInteger32Type) == kInteger32Type);
}
inline bool IsHeapNumber() {
ASSERT(type_ != kUninitializedType);
return ((type_ & kHeapNumberType) == kHeapNumberType);
}
inline bool IsUninitialized() {
return type_ == kUninitializedType;
}
const char* ToString() {
switch (type_) {
case kUnknownType: return "UnknownType";
case kNumberType: return "NumberType";
case kSmiType: return "SmiType";
case kHeapNumberType: return "HeapNumberType";
case kInteger32Type: return "Integer32Type";
case kUninitializedType:
UNREACHABLE();
return "UninitializedType";
}
UNREACHABLE();
return "Unreachable code";
}
private:
enum Type {
kUnknownType = 0,
kNumberType = 1,
kInteger32Type = 3,
kSmiType = 7,
kHeapNumberType = 9,
kUninitializedType = 15
};
explicit inline NumberInfo(Type t) : type_(t) { }
Type type_;
};
NumberInfo NumberInfo::Unknown() {
return NumberInfo(kUnknownType);
}
NumberInfo NumberInfo::Number() {
return NumberInfo(kNumberType);
}
NumberInfo NumberInfo::Integer32() {
return NumberInfo(kInteger32Type);
}
NumberInfo NumberInfo::Smi() {
return NumberInfo(kSmiType);
}
NumberInfo NumberInfo::HeapNumber() {
return NumberInfo(kHeapNumberType);
}
NumberInfo NumberInfo::Uninitialized() {
return NumberInfo(kUninitializedType);
}
} } // namespace v8::internal
#endif // V8_NUMBER_INFO_H_

497
deps/v8/src/regexp-delay.js

@ -1,497 +0,0 @@
// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 THE COPYRIGHT
// OWNER 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.
// Expect $Object = global.Object;
// Expect $Array = global.Array;
const $RegExp = global.RegExp;
// A recursive descent parser for Patterns according to the grammar of
// ECMA-262 15.10.1, with deviations noted below.
function DoConstructRegExp(object, pattern, flags, isConstructorCall) {
// RegExp : Called as constructor; see ECMA-262, section 15.10.4.
if (IS_REGEXP(pattern)) {
if (!IS_UNDEFINED(flags)) {
throw MakeTypeError('regexp_flags', []);
}
flags = (pattern.global ? 'g' : '')
+ (pattern.ignoreCase ? 'i' : '')
+ (pattern.multiline ? 'm' : '');
pattern = pattern.source;
}
pattern = IS_UNDEFINED(pattern) ? '' : ToString(pattern);
flags = IS_UNDEFINED(flags) ? '' : ToString(flags);
var global = false;
var ignoreCase = false;
var multiline = false;
for (var i = 0; i < flags.length; i++) {
var c = StringCharAt.call(flags, i);
switch (c) {
case 'g':
// Allow duplicate flags to be consistent with JSC and others.
global = true;
break;
case 'i':
ignoreCase = true;
break;
case 'm':
multiline = true;
break;
default:
// Ignore flags that have no meaning to be consistent with
// JSC.
break;
}
}
if (isConstructorCall) {
// ECMA-262, section 15.10.7.1.
%SetProperty(object, 'source', pattern,
DONT_DELETE | READ_ONLY | DONT_ENUM);
// ECMA-262, section 15.10.7.2.
%SetProperty(object, 'global', global, DONT_DELETE | READ_ONLY | DONT_ENUM);
// ECMA-262, section 15.10.7.3.
%SetProperty(object, 'ignoreCase', ignoreCase,
DONT_DELETE | READ_ONLY | DONT_ENUM);
// ECMA-262, section 15.10.7.4.
%SetProperty(object, 'multiline', multiline,
DONT_DELETE | READ_ONLY | DONT_ENUM);
// ECMA-262, section 15.10.7.5.
%SetProperty(object, 'lastIndex', 0, DONT_DELETE | DONT_ENUM);
} else { // RegExp is being recompiled via RegExp.prototype.compile.
%IgnoreAttributesAndSetProperty(object, 'source', pattern);
%IgnoreAttributesAndSetProperty(object, 'global', global);
%IgnoreAttributesAndSetProperty(object, 'ignoreCase', ignoreCase);
%IgnoreAttributesAndSetProperty(object, 'multiline', multiline);
%IgnoreAttributesAndSetProperty(object, 'lastIndex', 0);
regExpCache.type = 'none';
}
// Call internal function to compile the pattern.
%RegExpCompile(object, pattern, flags);
}
function RegExpConstructor(pattern, flags) {
if (%_IsConstructCall()) {
DoConstructRegExp(this, pattern, flags, true);
} else {
// RegExp : Called as function; see ECMA-262, section 15.10.3.1.
if (IS_REGEXP(pattern) && IS_UNDEFINED(flags)) {
return pattern;
}
return new $RegExp(pattern, flags);
}
}
// Deprecated RegExp.prototype.compile method. We behave like the constructor
// were called again. In SpiderMonkey, this method returns the regexp object.
// In JSC, it returns undefined. For compatibility with JSC, we match their
// behavior.
function CompileRegExp(pattern, flags) {
// Both JSC and SpiderMonkey treat a missing pattern argument as the
// empty subject string, and an actual undefined value passed as the
// pattern as the string 'undefined'. Note that JSC is inconsistent
// here, treating undefined values differently in
// RegExp.prototype.compile and in the constructor, where they are
// the empty string. For compatibility with JSC, we match their
// behavior.
if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) {
DoConstructRegExp(this, 'undefined', flags, false);
} else {
DoConstructRegExp(this, pattern, flags, false);
}
}
function DoRegExpExec(regexp, string, index) {
return %_RegExpExec(regexp, string, index, lastMatchInfo);
}
function RegExpCache() {
this.type = 'none';
this.regExp = 0;
this.subject = 0;
this.replaceString = 0;
this.lastIndex = 0;
this.answer = 0;
}
var regExpCache = new RegExpCache();
function CloneRegexpAnswer(array) {
var len = array.length;
var answer = new $Array(len);
for (var i = 0; i < len; i++) {
answer[i] = array[i];
}
answer.index = array.index;
answer.input = array.input;
return answer;
}
function RegExpExec(string) {
if (!IS_REGEXP(this)) {
throw MakeTypeError('incompatible_method_receiver',
['RegExp.prototype.exec', this]);
}
var cache = regExpCache;
if (%_ObjectEquals(cache.type, 'exec') &&
%_ObjectEquals(cache.lastIndex, this.lastIndex) &&
%_ObjectEquals(cache.regExp, this) &&
%_ObjectEquals(cache.subject, string)) {
var last = cache.answer;
if (last == null) {
return last;
} else {
return CloneRegexpAnswer(last);
}
}
if (%_ArgumentsLength() == 0) {
var regExpInput = LAST_INPUT(lastMatchInfo);
if (IS_UNDEFINED(regExpInput)) {
throw MakeError('no_input_to_regexp', [this]);
}
string = regExpInput;
}
var s;
if (IS_STRING(string)) {
s = string;
} else {
s = ToString(string);
}
var lastIndex = this.lastIndex;
var i = this.global ? TO_INTEGER(lastIndex) : 0;
if (i < 0 || i > s.length) {
this.lastIndex = 0;
return null;
}
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
// matchIndices is either null or the lastMatchInfo array.
var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
if (matchIndices == null) {
if (this.global) this.lastIndex = 0;
cache.lastIndex = lastIndex;
cache.regExp = this;
cache.subject = s;
cache.answer = matchIndices; // Null.
cache.type = 'exec';
return matchIndices; // No match.
}
var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1;
var result;
if (numResults === 1) {
var matchStart = lastMatchInfo[CAPTURE(0)];
var matchEnd = lastMatchInfo[CAPTURE(1)];
result = [SubString(s, matchStart, matchEnd)];
} else {
result = new $Array(numResults);
for (var i = 0; i < numResults; i++) {
var matchStart = lastMatchInfo[CAPTURE(i << 1)];
var matchEnd = lastMatchInfo[CAPTURE((i << 1) + 1)];
if (matchStart != -1 && matchEnd != -1) {
result[i] = SubString(s, matchStart, matchEnd);
} else {
// Make sure the element is present. Avoid reading the undefined
// property from the global object since this may change.
result[i] = void 0;
}
}
}
result.index = lastMatchInfo[CAPTURE0];
result.input = s;
if (this.global) {
this.lastIndex = lastMatchInfo[CAPTURE1];
return result;
} else {
cache.regExp = this;
cache.subject = s;
cache.lastIndex = lastIndex;
cache.answer = result;
cache.type = 'exec';
return CloneRegexpAnswer(result);
}
}
// Section 15.10.6.3 doesn't actually make sense, but the intention seems to be
// that test is defined in terms of String.prototype.exec. However, it probably
// means the original value of String.prototype.exec, which is what everybody
// else implements.
function RegExpTest(string) {
if (!IS_REGEXP(this)) {
throw MakeTypeError('incompatible_method_receiver',
['RegExp.prototype.test', this]);
}
if (%_ArgumentsLength() == 0) {
var regExpInput = LAST_INPUT(lastMatchInfo);
if (IS_UNDEFINED(regExpInput)) {
throw MakeError('no_input_to_regexp', [this]);
}
string = regExpInput;
}
var s;
if (IS_STRING(string)) {
s = string;
} else {
s = ToString(string);
}
var lastIndex = this.lastIndex;
var cache = regExpCache;
if (%_ObjectEquals(cache.type, 'test') &&
%_ObjectEquals(cache.regExp, this) &&
%_ObjectEquals(cache.subject, string) &&
%_ObjectEquals(cache.lastIndex, lastIndex)) {
return cache.answer;
}
var length = s.length;
var i = this.global ? TO_INTEGER(lastIndex) : 0;
cache.type = 'test';
cache.regExp = this;
cache.subject = s;
cache.lastIndex = i;
if (i < 0 || i > s.length) {
this.lastIndex = 0;
cache.answer = false;
return false;
}
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
// matchIndices is either null or the lastMatchInfo array.
var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
if (matchIndices == null) {
if (this.global) this.lastIndex = 0;
cache.answer = false;
return false;
}
if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
cache.answer = true;
return true;
}
function RegExpToString() {
// If this.source is an empty string, output /(?:)/.
// http://bugzilla.mozilla.org/show_bug.cgi?id=225550
// ecma_2/RegExp/properties-001.js.
var src = this.source ? this.source : '(?:)';
var result = '/' + src + '/';
if (this.global)
result += 'g';
if (this.ignoreCase)
result += 'i';
if (this.multiline)
result += 'm';
return result;
}
// Getters for the static properties lastMatch, lastParen, leftContext, and
// rightContext of the RegExp constructor. The properties are computed based
// on the captures array of the last successful match and the subject string
// of the last successful match.
function RegExpGetLastMatch() {
var regExpSubject = LAST_SUBJECT(lastMatchInfo);
return SubString(regExpSubject,
lastMatchInfo[CAPTURE0],
lastMatchInfo[CAPTURE1]);
}
function RegExpGetLastParen() {
var length = NUMBER_OF_CAPTURES(lastMatchInfo);
if (length <= 2) return ''; // There were no captures.
// We match the SpiderMonkey behavior: return the substring defined by the
// last pair (after the first pair) of elements of the capture array even if
// it is empty.
var regExpSubject = LAST_SUBJECT(lastMatchInfo);
var start = lastMatchInfo[CAPTURE(length - 2)];
var end = lastMatchInfo[CAPTURE(length - 1)];
if (start != -1 && end != -1) {
return SubString(regExpSubject, start, end);
}
return "";
}
function RegExpGetLeftContext() {
return SubString(LAST_SUBJECT(lastMatchInfo),
0,
lastMatchInfo[CAPTURE0]);
}
function RegExpGetRightContext() {
var subject = LAST_SUBJECT(lastMatchInfo);
return SubString(subject,
lastMatchInfo[CAPTURE1],
subject.length);
}
// The properties $1..$9 are the first nine capturing substrings of the last
// successful match, or ''. The function RegExpMakeCaptureGetter will be
// called with indices from 1 to 9.
function RegExpMakeCaptureGetter(n) {
return function() {
var index = n * 2;
if (index >= NUMBER_OF_CAPTURES(lastMatchInfo)) return '';
var matchStart = lastMatchInfo[CAPTURE(index)];
var matchEnd = lastMatchInfo[CAPTURE(index + 1)];
if (matchStart == -1 || matchEnd == -1) return '';
return SubString(LAST_SUBJECT(lastMatchInfo), matchStart, matchEnd);
};
}
// Property of the builtins object for recording the result of the last
// regexp match. The property lastMatchInfo includes the matchIndices
// array of the last successful regexp match (an array of start/end index
// pairs for the match and all the captured substrings), the invariant is
// that there are at least two capture indeces. The array also contains
// the subject string for the last successful match.
var lastMatchInfo = [
2, // REGEXP_NUMBER_OF_CAPTURES
"", // Last subject.
void 0, // Last input - settable with RegExpSetInput.
0, // REGEXP_FIRST_CAPTURE + 0
0, // REGEXP_FIRST_CAPTURE + 1
];
// -------------------------------------------------------------------
function SetupRegExp() {
%FunctionSetInstanceClassName($RegExp, 'RegExp');
%FunctionSetPrototype($RegExp, new $Object());
%SetProperty($RegExp.prototype, 'constructor', $RegExp, DONT_ENUM);
%SetCode($RegExp, RegExpConstructor);
InstallFunctions($RegExp.prototype, DONT_ENUM, $Array(
"exec", RegExpExec,
"test", RegExpTest,
"toString", RegExpToString,
"compile", CompileRegExp
));
// The length of compile is 1 in SpiderMonkey.
%FunctionSetLength($RegExp.prototype.compile, 1);
// The properties input, $input, and $_ are aliases for each other. When this
// value is set the value it is set to is coerced to a string.
// Getter and setter for the input.
function RegExpGetInput() {
var regExpInput = LAST_INPUT(lastMatchInfo);
return IS_UNDEFINED(regExpInput) ? "" : regExpInput;
}
function RegExpSetInput(string) {
regExpCache.type = 'none';
LAST_INPUT(lastMatchInfo) = ToString(string);
};
%DefineAccessor($RegExp, 'input', GETTER, RegExpGetInput, DONT_DELETE);
%DefineAccessor($RegExp, 'input', SETTER, RegExpSetInput, DONT_DELETE);
%DefineAccessor($RegExp, '$_', GETTER, RegExpGetInput, DONT_ENUM | DONT_DELETE);
%DefineAccessor($RegExp, '$_', SETTER, RegExpSetInput, DONT_ENUM | DONT_DELETE);
%DefineAccessor($RegExp, '$input', GETTER, RegExpGetInput, DONT_ENUM | DONT_DELETE);
%DefineAccessor($RegExp, '$input', SETTER, RegExpSetInput, DONT_ENUM | DONT_DELETE);
// The properties multiline and $* are aliases for each other. When this
// value is set in SpiderMonkey, the value it is set to is coerced to a
// boolean. We mimic that behavior with a slight difference: in SpiderMonkey
// the value of the expression 'RegExp.multiline = null' (for instance) is the
// boolean false (ie, the value after coercion), while in V8 it is the value
// null (ie, the value before coercion).
// Getter and setter for multiline.
var multiline = false;
function RegExpGetMultiline() { return multiline; };
function RegExpSetMultiline(flag) { multiline = flag ? true : false; };
%DefineAccessor($RegExp, 'multiline', GETTER, RegExpGetMultiline, DONT_DELETE);
%DefineAccessor($RegExp, 'multiline', SETTER, RegExpSetMultiline, DONT_DELETE);
%DefineAccessor($RegExp, '$*', GETTER, RegExpGetMultiline, DONT_ENUM | DONT_DELETE);
%DefineAccessor($RegExp, '$*', SETTER, RegExpSetMultiline, DONT_ENUM | DONT_DELETE);
function NoOpSetter(ignored) {}
// Static properties set by a successful match.
%DefineAccessor($RegExp, 'lastMatch', GETTER, RegExpGetLastMatch, DONT_DELETE);
%DefineAccessor($RegExp, 'lastMatch', SETTER, NoOpSetter, DONT_DELETE);
%DefineAccessor($RegExp, '$&', GETTER, RegExpGetLastMatch, DONT_ENUM | DONT_DELETE);
%DefineAccessor($RegExp, '$&', SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
%DefineAccessor($RegExp, 'lastParen', GETTER, RegExpGetLastParen, DONT_DELETE);
%DefineAccessor($RegExp, 'lastParen', SETTER, NoOpSetter, DONT_DELETE);
%DefineAccessor($RegExp, '$+', GETTER, RegExpGetLastParen, DONT_ENUM | DONT_DELETE);
%DefineAccessor($RegExp, '$+', SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
%DefineAccessor($RegExp, 'leftContext', GETTER, RegExpGetLeftContext, DONT_DELETE);
%DefineAccessor($RegExp, 'leftContext', SETTER, NoOpSetter, DONT_DELETE);
%DefineAccessor($RegExp, '$`', GETTER, RegExpGetLeftContext, DONT_ENUM | DONT_DELETE);
%DefineAccessor($RegExp, '$`', SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
%DefineAccessor($RegExp, 'rightContext', GETTER, RegExpGetRightContext, DONT_DELETE);
%DefineAccessor($RegExp, 'rightContext', SETTER, NoOpSetter, DONT_DELETE);
%DefineAccessor($RegExp, "$'", GETTER, RegExpGetRightContext, DONT_ENUM | DONT_DELETE);
%DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
for (var i = 1; i < 10; ++i) {
%DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_DELETE);
%DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE);
}
}
SetupRegExp();
Loading…
Cancel
Save