Browse Source

Upgrade v8 to 2.0.2

v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
4129305b7c
  1. 15
      deps/v8/ChangeLog
  2. 2
      deps/v8/src/allocation.h
  3. 45
      deps/v8/src/arm/codegen-arm.cc
  4. 2
      deps/v8/src/arm/codegen-arm.h
  5. 6
      deps/v8/src/builtins.cc
  6. 4
      deps/v8/src/codegen.cc
  7. 2
      deps/v8/src/flag-definitions.h
  8. 52
      deps/v8/src/heap.cc
  9. 1
      deps/v8/src/heap.h
  10. 49
      deps/v8/src/ia32/codegen-ia32.cc
  11. 2
      deps/v8/src/ia32/codegen-ia32.h
  12. 2
      deps/v8/src/log-inl.h
  13. 49
      deps/v8/src/log.cc
  14. 11
      deps/v8/src/log.h
  15. 5
      deps/v8/src/macros.py
  16. 13
      deps/v8/src/objects-inl.h
  17. 90
      deps/v8/src/objects.cc
  18. 2
      deps/v8/src/objects.h
  19. 28
      deps/v8/src/runtime.cc
  20. 8
      deps/v8/src/serialize.cc
  21. 2
      deps/v8/src/v8.cc
  22. 2
      deps/v8/src/version.cc
  23. 42
      deps/v8/src/x64/codegen-x64.cc
  24. 2
      deps/v8/src/x64/codegen-x64.h
  25. 66
      deps/v8/test/cctest/test-log.cc
  26. 45
      deps/v8/test/cctest/test-thread-termination.cc
  27. 40
      deps/v8/test/mjsunit/regress/regress-515.js
  28. 1
      deps/v8/tools/gyp/v8.gyp

15
deps/v8/ChangeLog

@ -1,3 +1,18 @@
2009-11-24: Version 2.0.2
Improved profiler support.
Fixed bug that broke compilation of d8 with readline support.
2009-11-20: Version 2.0.1
Fixed crash bug in String.prototype.replace.
Reverted a change which caused Chromium interactive ui test
failures.
2009-11-18: Version 2.0.0
Added support for VFP on ARM.

2
deps/v8/src/allocation.h

@ -124,7 +124,7 @@ static void DeleteArray(T* array) {
// and StrNDup uses new and calls the FatalProcessOutOfMemory handler
// if allocation fails.
char* StrDup(const char* str);
char* StrNDup(const char* str, size_t n);
char* StrNDup(const char* str, int n);
// Allocation policy for allocating in the C free store using malloc

45
deps/v8/src/arm/codegen-arm.cc

@ -3385,6 +3385,51 @@ void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
}
void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
// This generates a fast version of:
// (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp')
VirtualFrame::SpilledScope spilled_scope;
ASSERT(args->length() == 1);
LoadAndSpill(args->at(0));
frame_->EmitPop(r1);
__ tst(r1, Operand(kSmiTagMask));
false_target()->Branch(eq);
__ LoadRoot(ip, Heap::kNullValueRootIndex);
__ cmp(r1, ip);
true_target()->Branch(eq);
Register map_reg = r2;
__ ldr(map_reg, FieldMemOperand(r1, HeapObject::kMapOffset));
// Undetectable objects behave like undefined when tested with typeof.
__ ldrb(r1, FieldMemOperand(map_reg, Map::kBitFieldOffset));
__ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
__ cmp(r1, Operand(1 << Map::kIsUndetectable));
false_target()->Branch(eq);
__ ldrb(r1, FieldMemOperand(map_reg, Map::kInstanceTypeOffset));
__ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
false_target()->Branch(lt);
__ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
cc_reg_ = le;
}
void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
// This generates a fast version of:
// (%_ClassOf(arg) === 'Function')
VirtualFrame::SpilledScope spilled_scope;
ASSERT(args->length() == 1);
LoadAndSpill(args->at(0));
frame_->EmitPop(r0);
__ tst(r0, Operand(kSmiTagMask));
false_target()->Branch(eq);
Register map_reg = r2;
__ CompareObjectType(r0, map_reg, r1, JS_FUNCTION_TYPE);
cc_reg_ = eq;
}
void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope;
ASSERT(args->length() == 0);

2
deps/v8/src/arm/codegen-arm.h

@ -334,6 +334,8 @@ class CodeGenerator: public AstVisitor {
void GenerateIsSmi(ZoneList<Expression*>* args);
void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
void GenerateIsArray(ZoneList<Expression*>* args);
void GenerateIsObject(ZoneList<Expression*>* args);
void GenerateIsFunction(ZoneList<Expression*>* args);
// Support for construct call checks.
void GenerateIsConstructCall(ZoneList<Expression*>* args);

6
deps/v8/src/builtins.cc

@ -380,6 +380,9 @@ BUILTIN(HandleApiCall) {
{
// Leaving JavaScript.
VMState state(EXTERNAL);
#ifdef ENABLE_LOGGING_AND_PROFILING
state.set_external_callback(v8::ToCData<Address>(callback_obj));
#endif
value = callback(new_args);
}
if (value.IsEmpty()) {
@ -446,6 +449,9 @@ static Object* HandleApiCallAsFunctionOrConstructor(bool is_construct_call,
{
// Leaving JavaScript.
VMState state(EXTERNAL);
#ifdef ENABLE_LOGGING_AND_PROFILING
state.set_external_callback(v8::ToCData<Address>(callback_obj));
#endif
value = callback(new_args);
}
if (value.IsEmpty()) {

4
deps/v8/src/codegen.cc

@ -343,7 +343,9 @@ CodeGenerator::InlineRuntimeLUT CodeGenerator::kInlineRuntimeLUT[] = {
{&CodeGenerator::GenerateLog, "_Log"},
{&CodeGenerator::GenerateRandomPositiveSmi, "_RandomPositiveSmi"},
{&CodeGenerator::GenerateMathSin, "_Math_sin"},
{&CodeGenerator::GenerateMathCos, "_Math_cos"}
{&CodeGenerator::GenerateMathCos, "_Math_cos"},
{&CodeGenerator::GenerateIsObject, "_IsObject"},
{&CodeGenerator::GenerateIsFunction, "_IsFunction"},
};

2
deps/v8/src/flag-definitions.h

@ -143,7 +143,7 @@ DEFINE_bool(debug_info, true, "add debug information to compiled functions")
DEFINE_bool(strict, false, "strict error checking")
DEFINE_int(min_preparse_length, 1024,
"minimum length for automatic enable preparsing")
DEFINE_bool(fast_compiler, true,
DEFINE_bool(fast_compiler, false,
"use the fast-mode compiler for some top-level code")
DEFINE_bool(trace_bailout, false,
"print reasons for failing to use fast compilation")

52
deps/v8/src/heap.cc

@ -1762,6 +1762,41 @@ Object* Heap::AllocateSharedFunctionInfo(Object* name) {
}
// Returns true for a character in a range. Both limits are inclusive.
static inline bool Between(uint32_t character, uint32_t from, uint32_t to) {
// This makes uses of the the unsigned wraparound.
return character - from <= to - from;
}
static inline Object* MakeOrFindTwoCharacterString(uint32_t c1, uint32_t c2) {
String* symbol;
// Numeric strings have a different hash algorithm not known by
// LookupTwoCharsSymbolIfExists, so we skip this step for such strings.
if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) &&
Heap::symbol_table()->LookupTwoCharsSymbolIfExists(c1, c2, &symbol)) {
return symbol;
// Now we know the length is 2, we might as well make use of that fact
// when building the new string.
} else if ((c1 | c2) <= String::kMaxAsciiCharCodeU) { // We can do this
ASSERT(IsPowerOf2(String::kMaxAsciiCharCodeU + 1)); // because of this.
Object* result = Heap::AllocateRawAsciiString(2);
if (result->IsFailure()) return result;
char* dest = SeqAsciiString::cast(result)->GetChars();
dest[0] = c1;
dest[1] = c2;
return result;
} else {
Object* result = Heap::AllocateRawTwoByteString(2);
if (result->IsFailure()) return result;
uc16* dest = SeqTwoByteString::cast(result)->GetChars();
dest[0] = c1;
dest[1] = c2;
return result;
}
}
Object* Heap::AllocateConsString(String* first, String* second) {
int first_length = first->length();
if (first_length == 0) {
@ -1774,6 +1809,16 @@ Object* Heap::AllocateConsString(String* first, String* second) {
}
int length = first_length + second_length;
// Optimization for 2-byte strings often used as keys in a decompression
// dictionary. Check whether we already have the string in the symbol
// table to prevent creation of many unneccesary strings.
if (length == 2) {
unsigned c1 = first->Get(0);
unsigned c2 = second->Get(0);
return MakeOrFindTwoCharacterString(c1, c2);
}
bool is_ascii = first->IsAsciiRepresentation()
&& second->IsAsciiRepresentation();
@ -1843,6 +1888,13 @@ Object* Heap::AllocateSubString(String* buffer,
if (length == 1) {
return Heap::LookupSingleCharacterStringFromCode(
buffer->Get(start));
} else if (length == 2) {
// Optimization for 2-byte strings often used as keys in a decompression
// dictionary. Check whether we already have the string in the symbol
// table to prevent creation of many unneccesary strings.
unsigned c1 = buffer->Get(start);
unsigned c2 = buffer->Get(start + 1);
return MakeOrFindTwoCharacterString(c1, c2);
}
// Make an attempt to flatten the buffer to reduce access time.

1
deps/v8/src/heap.h

@ -631,6 +631,7 @@ class Heap : public AllStatic {
}
static Object* LookupSymbol(String* str);
static bool LookupSymbolIfExists(String* str, String** symbol);
static bool LookupTwoCharsSymbolIfExists(String* str, String** symbol);
// Compute the matching symbol map for a string if possible.
// NULL is returned if string is in new space or not flattened.

49
deps/v8/src/ia32/codegen-ia32.cc

@ -4870,6 +4870,55 @@ void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
}
void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
// This generates a fast version of:
// (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp')
ASSERT(args->length() == 1);
Load(args->at(0));
Result obj = frame_->Pop();
obj.ToRegister();
__ test(obj.reg(), Immediate(kSmiTagMask));
destination()->false_target()->Branch(zero);
__ cmp(obj.reg(), Factory::null_value());
destination()->true_target()->Branch(equal);
Result map = allocator()->Allocate();
ASSERT(map.is_valid());
__ mov(map.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset));
// Undetectable objects behave like undefined when tested with typeof.
__ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kBitFieldOffset));
__ test(map.reg(), Immediate(1 << Map::kIsUndetectable));
destination()->false_target()->Branch(not_zero);
__ mov(map.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset));
__ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset));
__ cmp(map.reg(), FIRST_JS_OBJECT_TYPE);
destination()->false_target()->Branch(less);
__ cmp(map.reg(), LAST_JS_OBJECT_TYPE);
obj.Unuse();
map.Unuse();
destination()->Split(less_equal);
}
void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
// This generates a fast version of:
// (%_ClassOf(arg) === 'Function')
ASSERT(args->length() == 1);
Load(args->at(0));
Result obj = frame_->Pop();
obj.ToRegister();
__ test(obj.reg(), Immediate(kSmiTagMask));
destination()->false_target()->Branch(zero);
Result temp = allocator()->Allocate();
ASSERT(temp.is_valid());
__ CmpObjectType(obj.reg(), JS_FUNCTION_TYPE, temp.reg());
obj.Unuse();
temp.Unuse();
destination()->Split(equal);
}
void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
ASSERT(args->length() == 0);

2
deps/v8/src/ia32/codegen-ia32.h

@ -512,6 +512,8 @@ class CodeGenerator: public AstVisitor {
void GenerateIsSmi(ZoneList<Expression*>* args);
void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
void GenerateIsArray(ZoneList<Expression*>* args);
void GenerateIsObject(ZoneList<Expression*>* args);
void GenerateIsFunction(ZoneList<Expression*>* args);
// Support for construct call checks.
void GenerateIsConstructCall(ZoneList<Expression*>* args);

2
deps/v8/src/log-inl.h

@ -55,7 +55,7 @@ inline const char* StateToString(StateTag state) {
}
}
VMState::VMState(StateTag state) : disabled_(true) {
VMState::VMState(StateTag state) : disabled_(true), external_callback_(NULL) {
if (!Logger::is_logging()) {
return;
}

49
deps/v8/src/log.cc

@ -30,6 +30,7 @@
#include "v8.h"
#include "bootstrapper.h"
#include "global-handles.h"
#include "log.h"
#include "macro-assembler.h"
#include "serialize.h"
@ -154,12 +155,18 @@ void StackTracer::Trace(TickSample* sample) {
return;
}
int i = 0;
const Address callback = Logger::current_state_ != NULL ?
Logger::current_state_->external_callback() : NULL;
if (callback != NULL) {
sample->stack[i++] = callback;
}
SafeStackTraceFrameIterator it(
reinterpret_cast<Address>(sample->fp),
reinterpret_cast<Address>(sample->sp),
reinterpret_cast<Address>(sample->sp),
js_entry_sp);
int i = 0;
while (!it.done() && i < TickSample::kMaxFramesCount) {
sample->stack[i++] = it.frame()->pc();
it.Advance();
@ -673,6 +680,26 @@ class CompressionHelper {
#endif // ENABLE_LOGGING_AND_PROFILING
void Logger::CallbackEvent(String* name, Address entry_point) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (!Log::IsEnabled() || !FLAG_log_code) return;
LogMessageBuilder msg;
msg.Append("%s,%s,",
log_events_[CODE_CREATION_EVENT], log_events_[CALLBACK_TAG]);
msg.AppendAddress(entry_point);
SmartPointer<char> str =
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
msg.Append(",1,\"%s\"", *str);
if (FLAG_compress_log) {
ASSERT(compression_helper_ != NULL);
if (!compression_helper_->HandleMessage(&msg)) return;
}
msg.Append('\n');
msg.WriteToLogFile();
#endif
}
void Logger::CodeCreateEvent(LogEventsAndTags tag,
Code* code,
const char* comment) {
@ -1191,11 +1218,25 @@ void Logger::LogCompiledFunctions() {
LOG(CodeCreateEvent(Logger::SCRIPT_TAG,
shared->code(), *script_name));
}
continue;
} else {
LOG(CodeCreateEvent(
Logger::LAZY_COMPILE_TAG, shared->code(), *func_name));
}
} else if (shared->function_data()->IsFunctionTemplateInfo()) {
// API function.
FunctionTemplateInfo* fun_data =
FunctionTemplateInfo::cast(shared->function_data());
Object* raw_call_data = fun_data->call_code();
if (!raw_call_data->IsUndefined()) {
CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
Object* callback_obj = call_data->callback();
Address entry_point = v8::ToCData<Address>(callback_obj);
LOG(CallbackEvent(*func_name, entry_point));
}
} else {
LOG(CodeCreateEvent(
Logger::LAZY_COMPILE_TAG, shared->code(), *func_name));
}
// If no script or script has no name.
LOG(CodeCreateEvent(Logger::LAZY_COMPILE_TAG, shared->code(), *func_name));
}
DeleteArray(sfis);

11
deps/v8/src/log.h

@ -91,15 +91,20 @@ class CompressionHelper;
class VMState BASE_EMBEDDED {
#ifdef ENABLE_LOGGING_AND_PROFILING
public:
inline explicit VMState(StateTag state);
inline VMState(StateTag state);
inline ~VMState();
StateTag state() { return state_; }
Address external_callback() { return external_callback_; }
void set_external_callback(Address external_callback) {
external_callback_ = external_callback;
}
private:
bool disabled_;
StateTag state_;
VMState* previous_;
Address external_callback_;
#else
public:
explicit VMState(StateTag state) {}
@ -122,6 +127,7 @@ class VMState BASE_EMBEDDED {
V(CALL_MISS_TAG, "CallMiss", "cm") \
V(CALL_NORMAL_TAG, "CallNormal", "cn") \
V(CALL_PRE_MONOMORPHIC_TAG, "CallPreMonomorphic", "cpm") \
V(CALLBACK_TAG, "Callback", "cb") \
V(EVAL_TAG, "Eval", "e") \
V(FUNCTION_TAG, "Function", "f") \
V(KEYED_LOAD_IC_TAG, "KeyedLoadIC", "klic") \
@ -200,6 +206,8 @@ class Logger {
// ==== Events logged by --log-code. ====
// Emits a code event for a callback function.
static void CallbackEvent(String* name, Address entry_point);
// Emits a code create event.
static void CodeCreateEvent(LogEventsAndTags tag,
Code* code, const char* source);
@ -330,6 +338,7 @@ class Logger {
friend class TimeLog;
friend class Profiler;
friend class SlidingStateWindow;
friend class StackTracer;
friend class VMState;
friend class LoggerTestHelper;

5
deps/v8/src/macros.py

@ -79,11 +79,10 @@ macro IS_NULL_OR_UNDEFINED(arg) = (arg == null);
macro IS_UNDEFINED(arg) = (typeof(arg) === 'undefined');
macro IS_NUMBER(arg) = (typeof(arg) === 'number');
macro IS_STRING(arg) = (typeof(arg) === 'string');
macro IS_OBJECT(arg) = (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp');
macro IS_BOOLEAN(arg) = (typeof(arg) === 'boolean');
macro IS_OBJECT(arg) = (%_IsObject(arg));
macro IS_ARRAY(arg) = (%_IsArray(arg));
# IS_FUNCTION uses %_ClassOf rather than typeof so as to exclude regexps.
macro IS_FUNCTION(arg) = (%_ClassOf(arg) === 'Function');
macro IS_FUNCTION(arg) = (%_IsFunction(arg));
macro IS_REGEXP(arg) = (%_ClassOf(arg) === 'RegExp');
macro IS_DATE(arg) = (%_ClassOf(arg) === 'Date');
macro IS_NUMBER_WRAPPER(arg) = (%_ClassOf(arg) === 'Number');

13
deps/v8/src/objects-inl.h

@ -3103,8 +3103,19 @@ void Map::ClearCodeCache() {
void JSArray::EnsureSize(int required_size) {
ASSERT(HasFastElements());
if (elements()->length() >= required_size) return;
Array* elts = elements();
const int kArraySizeThatFitsComfortablyInNewSpace = 128;
if (elts->length() < required_size) {
// Doubling in size would be overkill, but leave some slack to avoid
// constantly growing.
Expand(required_size + (required_size >> 3));
// It's a performance benefit to keep a frequently used array in new-space.
} else if (!Heap::new_space()->Contains(elts) &&
required_size < kArraySizeThatFitsComfortablyInNewSpace) {
// Expand will allocate a new backing store in new space even if the size
// we asked for isn't larger than what we had before.
Expand(required_size);
}
}

90
deps/v8/src/objects.cc

@ -1478,6 +1478,7 @@ Object* JSObject::ReplaceSlowProperty(String* name,
return SetNormalizedProperty(name, value, new_details);
}
Object* JSObject::ConvertDescriptorToFieldAndMapTransition(
String* name,
Object* new_value,
@ -1869,6 +1870,14 @@ Object* JSObject::SetProperty(LookupResult* result,
// interceptor calls.
AssertNoContextChange ncc;
// Optimization for 2-byte strings often used as keys in a decompression
// dictionary. We make these short keys into symbols to avoid constantly
// reallocating them.
if (!name->IsSymbol() && name->length() <= 2) {
Object* symbol_version = Heap::LookupSymbol(name);
if (!symbol_version->IsFailure()) name = String::cast(symbol_version);
}
// Check access rights if needed.
if (IsAccessCheckNeeded()
&& !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
@ -5240,9 +5249,7 @@ void JSArray::Expand(int required_size) {
Handle<JSArray> self(this);
Handle<FixedArray> old_backing(FixedArray::cast(elements()));
int old_size = old_backing->length();
// Doubling in size would be overkill, but leave some slack to avoid
// constantly growing.
int new_size = required_size + (required_size >> 3);
int new_size = required_size > old_size ? required_size : old_size;
Handle<FixedArray> new_backing = Factory::NewFixedArray(new_size);
// Can't use this any more now because we may have had a GC!
for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i));
@ -7327,6 +7334,67 @@ Object* SymbolTable::LookupString(String* string, Object** s) {
}
// This class is used for looking up two character strings in the symbol table.
// If we don't have a hit we don't want to waste much time so we unroll the
// string hash calculation loop here for speed. Doesn't work if the two
// characters form a decimal integer, since such strings have a different hash
// algorithm.
class TwoCharHashTableKey : public HashTableKey {
public:
TwoCharHashTableKey(uint32_t c1, uint32_t c2)
: c1_(c1), c2_(c2) {
// Char 1.
uint32_t hash = c1 + (c1 << 10);
hash ^= hash >> 6;
// Char 2.
hash += c2;
hash += hash << 10;
hash ^= hash >> 6;
// GetHash.
hash += hash << 3;
hash ^= hash >> 11;
hash += hash << 15;
if (hash == 0) hash = 27;
#ifdef DEBUG
StringHasher hasher(2);
hasher.AddCharacter(c1);
hasher.AddCharacter(c2);
// If this assert fails then we failed to reproduce the two-character
// version of the string hashing algorithm above. One reason could be
// that we were passed two digits as characters, since the hash
// algorithm is different in that case.
ASSERT_EQ(static_cast<int>(hasher.GetHash()), static_cast<int>(hash));
#endif
hash_ = hash;
}
bool IsMatch(Object* o) {
if (!o->IsString()) return false;
String* other = String::cast(o);
if (other->length() != 2) return false;
if (other->Get(0) != c1_) return false;
return other->Get(1) == c2_;
}
uint32_t Hash() { return hash_; }
uint32_t HashForObject(Object* key) {
if (!key->IsString()) return 0;
return String::cast(key)->Hash();
}
Object* AsObject() {
// The TwoCharHashTableKey is only used for looking in the symbol
// table, not for adding to it.
UNREACHABLE();
return NULL;
}
private:
uint32_t c1_;
uint32_t c2_;
uint32_t hash_;
};
bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
SymbolKey key(string);
int entry = FindEntry(&key);
@ -7341,6 +7409,22 @@ bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
}
bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1,
uint32_t c2,
String** symbol) {
TwoCharHashTableKey key(c1, c2);
int entry = FindEntry(&key);
if (entry == kNotFound) {
return false;
} else {
String* result = String::cast(KeyAt(entry));
ASSERT(StringShape(result).IsSymbol());
*symbol = result;
return true;
}
}
Object* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) {
Utf8SymbolKey key(str);
return LookupKey(&key, s);

2
deps/v8/src/objects.h

@ -2188,6 +2188,7 @@ class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
// true if it is found, assigning the symbol to the given output
// parameter.
bool LookupSymbolIfExists(String* str, String** symbol);
bool LookupTwoCharsSymbolIfExists(uint32_t c1, uint32_t c2, String** symbol);
// Casting.
static inline SymbolTable* cast(Object* obj);
@ -3846,6 +3847,7 @@ class StringHasher {
bool is_array_index_;
bool is_first_char_;
bool is_valid_;
friend class TwoCharHashTableKey;
};

28
deps/v8/src/runtime.cc

@ -1750,10 +1750,10 @@ static Object* StringReplaceRegExpWithString(String* subject,
// Index of end of last match.
int prev = 0;
// Number of parts added by compiled replacement plus preceeding string
// and possibly suffix after last match. It is possible for compiled
// replacements to use two elements when encoded as two smis.
const int parts_added_per_loop = compiled_replacement.parts() * 2 + 2;
// Number of parts added by compiled replacement plus preceeding
// string and possibly suffix after last match. It is possible for
// all components to use two elements when encoded as two smis.
const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
bool matched = true;
do {
ASSERT(last_match_info_handle->HasFastElements());
@ -2356,12 +2356,20 @@ static Object* Runtime_SubString(Arguments args) {
ASSERT(args.length() == 3);
CONVERT_CHECKED(String, value, args[0]);
CONVERT_DOUBLE_CHECKED(from_number, args[1]);
CONVERT_DOUBLE_CHECKED(to_number, args[2]);
int start = FastD2I(from_number);
int end = FastD2I(to_number);
Object* from = args[1];
Object* to = args[2];
int start, end;
// We have a fast integer-only case here to avoid a conversion to double in
// the common case where from and to are Smis.
if (from->IsSmi() && to->IsSmi()) {
start = Smi::cast(from)->value();
end = Smi::cast(to)->value();
} else {
CONVERT_DOUBLE_CHECKED(from_number, from);
CONVERT_DOUBLE_CHECKED(to_number, to);
start = FastD2I(from_number);
end = FastD2I(to_number);
}
RUNTIME_ASSERT(end >= start);
RUNTIME_ASSERT(start >= 0);
RUNTIME_ASSERT(end <= value->length());

8
deps/v8/src/serialize.cc

@ -668,7 +668,7 @@ void Deserializer::ReadChunk(Object** current,
break;
case OBJECT_SERIALIZATION + CODE_SPACE:
ReadObject(CODE_SPACE, Heap::code_space(), current++);
Logger::LogCodeObject(current[-1]);
LOG(LogCodeObject(current[-1]));
break;
case OBJECT_SERIALIZATION + CELL_SPACE:
ReadObject(CELL_SPACE, Heap::cell_space(), current++);
@ -678,7 +678,7 @@ void Deserializer::ReadChunk(Object** current,
break;
case OBJECT_SERIALIZATION + kLargeCode:
ReadObject(kLargeCode, Heap::lo_space(), current++);
Logger::LogCodeObject(current[-1]);
LOG(LogCodeObject(current[-1]));
break;
case OBJECT_SERIALIZATION + kLargeFixedArray:
ReadObject(kLargeFixedArray, Heap::lo_space(), current++);
@ -687,7 +687,7 @@ void Deserializer::ReadChunk(Object** current,
Object* new_code_object = NULL;
ReadObject(kLargeCode, Heap::lo_space(), &new_code_object);
Code* code_object = reinterpret_cast<Code*>(new_code_object);
Logger::LogCodeObject(code_object);
LOG(LogCodeObject(code_object));
// Setting a branch/call to another code object from code.
Address location_of_branch_data = reinterpret_cast<Address>(current);
Assembler::set_target_at(location_of_branch_data,
@ -700,7 +700,7 @@ void Deserializer::ReadChunk(Object** current,
Object* new_code_object = NULL;
ReadObject(CODE_SPACE, Heap::code_space(), &new_code_object);
Code* code_object = reinterpret_cast<Code*>(new_code_object);
Logger::LogCodeObject(code_object);
LOG(LogCodeObject(code_object));
// Setting a branch/call to another code object from code.
Address location_of_branch_data = reinterpret_cast<Address>(current);
Assembler::set_target_at(location_of_branch_data,

2
deps/v8/src/v8.cc

@ -116,7 +116,7 @@ bool V8::Initialize(Deserializer *des) {
if (FLAG_log_code) {
HandleScope scope;
Logger::LogCompiledFunctions();
LOG(LogCompiledFunctions());
}
return true;

2
deps/v8/src/version.cc

@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 2
#define MINOR_VERSION 0
#define BUILD_NUMBER 0
#define BUILD_NUMBER 2
#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false

42
deps/v8/src/x64/codegen-x64.cc

@ -3616,6 +3616,48 @@ void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
}
void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
// This generates a fast version of:
// (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp')
ASSERT(args->length() == 1);
Load(args->at(0));
Result obj = frame_->Pop();
obj.ToRegister();
Condition is_smi = masm_->CheckSmi(obj.reg());
destination()->false_target()->Branch(is_smi);
__ Move(kScratchRegister, Factory::null_value());
__ cmpq(obj.reg(), kScratchRegister);
destination()->true_target()->Branch(equal);
__ movq(kScratchRegister, FieldOperand(obj.reg(), HeapObject::kMapOffset));
// Undetectable objects behave like undefined when tested with typeof.
__ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset),
Immediate(1 << Map::kIsUndetectable));
destination()->false_target()->Branch(not_zero);
__ CmpInstanceType(kScratchRegister, FIRST_JS_OBJECT_TYPE);
destination()->false_target()->Branch(less);
__ CmpInstanceType(kScratchRegister, LAST_JS_OBJECT_TYPE);
obj.Unuse();
destination()->Split(less_equal);
}
void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
// This generates a fast version of:
// (%_ClassOf(arg) === 'Function')
ASSERT(args->length() == 1);
Load(args->at(0));
Result obj = frame_->Pop();
obj.ToRegister();
Condition is_smi = masm_->CheckSmi(obj.reg());
destination()->false_target()->Branch(is_smi);
__ CmpObjectType(obj.reg(), JS_FUNCTION_TYPE, kScratchRegister);
obj.Unuse();
destination()->Split(equal);
}
void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
ASSERT(args->length() == 0);

2
deps/v8/src/x64/codegen-x64.h

@ -510,6 +510,8 @@ class CodeGenerator: public AstVisitor {
void GenerateIsSmi(ZoneList<Expression*>* args);
void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
void GenerateIsArray(ZoneList<Expression*>* args);
void GenerateIsObject(ZoneList<Expression*>* args);
void GenerateIsFunction(ZoneList<Expression*>* args);
// Support for construct call checks.
void GenerateIsConstructCall(ZoneList<Expression*>* args);

66
deps/v8/test/cctest/test-log.cc

@ -247,7 +247,7 @@ TEST(ProfLazyMode) {
i::FLAG_logfile = "*";
// If tests are being run manually, V8 will be already initialized
// by the test below.
// by the bottom test.
const bool need_to_set_up_logger = i::V8::IsRunning();
v8::HandleScope scope;
v8::Handle<v8::Context> env = v8::Context::New();
@ -474,6 +474,70 @@ TEST(Issue23768) {
}
static v8::Handle<v8::Value> ObjMethod1(const v8::Arguments& args) {
return v8::Handle<v8::Value>();
}
TEST(LogCallbacks) {
const bool saved_prof_lazy = i::FLAG_prof_lazy;
const bool saved_prof = i::FLAG_prof;
const bool saved_prof_auto = i::FLAG_prof_auto;
i::FLAG_prof = true;
i::FLAG_prof_lazy = false;
i::FLAG_prof_auto = false;
i::FLAG_logfile = "*";
// If tests are being run manually, V8 will be already initialized
// by the bottom test.
const bool need_to_set_up_logger = i::V8::IsRunning();
v8::HandleScope scope;
v8::Handle<v8::Context> env = v8::Context::New();
if (need_to_set_up_logger) Logger::Setup();
env->Enter();
// Skip all initially logged stuff.
EmbeddedVector<char, 102400> buffer;
int log_pos = GetLogLines(0, &buffer);
v8::Persistent<v8::FunctionTemplate> obj =
v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New());
obj->SetClassName(v8::String::New("Obj"));
v8::Handle<v8::ObjectTemplate> proto = obj->PrototypeTemplate();
v8::Local<v8::Signature> signature = v8::Signature::New(obj);
proto->Set(v8::String::New("method1"),
v8::FunctionTemplate::New(ObjMethod1,
v8::Handle<v8::Value>(),
signature),
static_cast<v8::PropertyAttribute>(v8::DontDelete));
env->Global()->Set(v8_str("Obj"), obj->GetFunction());
CompileAndRunScript("Obj.prototype.method1.toString();");
i::Logger::LogCompiledFunctions();
log_pos = GetLogLines(log_pos, &buffer);
CHECK_GT(log_pos, 0);
buffer[log_pos] = 0;
const char* callback_rec = "code-creation,Callback,";
char* pos = strstr(buffer.start(), callback_rec);
CHECK_NE(NULL, pos);
pos += strlen(callback_rec);
EmbeddedVector<char, 100> ref_data;
i::OS::SNPrintF(ref_data,
"0x%" V8PRIxPTR ",1,\"method1\"", ObjMethod1);
*(pos + strlen(ref_data.start())) = '\0';
CHECK_EQ(ref_data.start(), pos);
obj.Dispose();
env->Exit();
Logger::TearDown();
i::FLAG_prof_lazy = saved_prof_lazy;
i::FLAG_prof = saved_prof;
i::FLAG_prof_auto = saved_prof_auto;
}
static inline bool IsStringEqualTo(const char* r, const char* s) {
return strncmp(r, s, strlen(r)) == 0;
}

45
deps/v8/test/cctest/test-thread-termination.cc

@ -82,14 +82,30 @@ v8::Handle<v8::Value> DoLoop(const v8::Arguments& args) {
}
v8::Handle<v8::Value> DoLoopNoCall(const v8::Arguments& args) {
v8::TryCatch try_catch;
v8::Script::Compile(v8::String::New("var term = true;"
"while(true) {"
" if (term) terminate();"
" term = false;"
"}"))->Run();
CHECK(try_catch.HasCaught());
CHECK(try_catch.Exception()->IsNull());
CHECK(try_catch.Message().IsEmpty());
CHECK(!try_catch.CanContinue());
return v8::Undefined();
}
v8::Handle<v8::ObjectTemplate> CreateGlobalTemplate(
v8::InvocationCallback terminate) {
v8::InvocationCallback terminate,
v8::InvocationCallback doloop) {
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
global->Set(v8::String::New("terminate"),
v8::FunctionTemplate::New(terminate));
global->Set(v8::String::New("fail"), v8::FunctionTemplate::New(Fail));
global->Set(v8::String::New("loop"), v8::FunctionTemplate::New(Loop));
global->Set(v8::String::New("doloop"), v8::FunctionTemplate::New(DoLoop));
global->Set(v8::String::New("doloop"), v8::FunctionTemplate::New(doloop));
return global;
}
@ -99,7 +115,25 @@ v8::Handle<v8::ObjectTemplate> CreateGlobalTemplate(
TEST(TerminateOnlyV8ThreadFromThreadItself) {
v8::HandleScope scope;
v8::Handle<v8::ObjectTemplate> global =
CreateGlobalTemplate(TerminateCurrentThread);
CreateGlobalTemplate(TerminateCurrentThread, DoLoop);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context);
// Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
v8::Script::Compile(source)->Run();
// Test that we can run the code again after thread termination.
v8::Script::Compile(source)->Run();
context.Dispose();
}
// Test that a single thread of JavaScript execution can terminate
// itself in a loop that performs no calls.
TEST(TerminateOnlyV8ThreadFromThreadItselfNoLoop) {
v8::HandleScope scope;
v8::Handle<v8::ObjectTemplate> global =
CreateGlobalTemplate(TerminateCurrentThread, DoLoopNoCall);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context);
// Run a loop that will be infinite if thread termination does not work.
@ -128,7 +162,7 @@ TEST(TerminateOnlyV8ThreadFromOtherThread) {
thread.Start();
v8::HandleScope scope;
v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal);
v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal, DoLoop);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context);
// Run a loop that will be infinite if thread termination does not work.
@ -149,7 +183,8 @@ class LoopingThread : public v8::internal::Thread {
v8::Locker locker;
v8::HandleScope scope;
v8_thread_id_ = v8::V8::GetCurrentThreadId();
v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal);
v8::Handle<v8::ObjectTemplate> global =
CreateGlobalTemplate(Signal, DoLoop);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context);
// Run a loop that will be infinite if thread termination does not work.

40
deps/v8/test/mjsunit/regress/regress-515.js

@ -0,0 +1,40 @@
// 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.
// Regression test for http://code.google.com/p/v8/issues/detail?id=515.
//
// The test passes if it does not crash.
var length = 2048;
var s = "";
for (var i = 0; i < 2048; i++) {
s += '.';
}
var string = s + 'x' + s + 'x' + s;
string.replace(/x/g, "")

1
deps/v8/tools/gyp/v8.gyp

@ -81,6 +81,7 @@
['OS=="linux"', {
'cflags!': [
'-O2',
'-Os',
],
'cflags': [
'-fomit-frame-pointer',

Loading…
Cancel
Save