This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Upgrade v8 to 2.0.2

  • Loading branch information...
ry committed Nov 27, 2009
1 parent dc093ef commit 4129305b7cdfb6df9695225e62714ab6e80fccd3
View
@@ -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.
View
@@ -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
@@ -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);
@@ -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);
View
@@ -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()) {
View
@@ -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"},
};
@@ -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")
View
@@ -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.
View
@@ -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.
@@ -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);
@@ -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);
View
@@ -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;
}
View
@@ -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);
Oops, something went wrong.

0 comments on commit 4129305

Please sign in to comment.