Commit 25b44b10 authored by Jérémy Lal's avatar Jérémy Lal

Imported Upstream version 0.4.3

parent c4cc0b44
......@@ -5,11 +5,10 @@ tags
*.pyc
doc/api.xml
tools/nodejs.pc
test/fixtures/hello.txt
tmp/
node
node_g
*.swp
.benchmark_reports
/.project
/.cproject
\ No newline at end of file
/.cproject
......@@ -162,3 +162,5 @@ Koichi Kobayashi <koichik@improvement.jp>
Daniel Gröber <dxld@darkboxed.org>
Konstantin Käfer <github@kkaefer.com>
Richard Rodger <richard@ricebridge.com>
Andreas Reich <andreas@reich.name>
Dean McNamee <dean@gmail.com>
2011.03.02, Version 0.4.2 (stable)
2011.03.18, Version 0.4.3 (stable)
* Don't decrease server connection counter again if destroy() is called more
than once GH-431 (Andreas Reich, Anders Conbere)
* Documentation improvements (koichik)
* Fix bug with setMaxListeners GH-682
* Start up memory footprint improvement. (Tom Hughes)
* Solaris improvements.
* Buffer::Length(Buffer*) should not invoke itself recursively GH-759 (Ben
Noordhuis)
* TLS: Advertise support for client certs GH-774 (Theo Schlossnagle)
* HTTP Agent bugs: GH-787, GH-784, GH-803.
* Don't call GetMemoryUsage every 5 seconds.
* Upgrade V8 to 3.1.8.3
2011.03.02, Version 0.4.2 (stable), 39280e1b5731f3fcd8cc42ad41b86cdfdcb6d58b
* Improve docs.
......
This license applies to all parts of Node that are not externally
maintained libraries. The externally maintained libraries used by Node
are:
- v8, located under deps/v8, which is copyrighted by the Google, Inc.
v8 has a BSD license.
- libev, located under deps/libev, and libeio, located at deps/libeio.
This code is copyrighted by Marc Alexander Lehmann. Both are dually
licensed under MIT and GPL2.
- WAF build system, located at tools/waf. Copyrighted Thomas Nagy.
Released under an MIT license.
- The SCONS build system, located at tools/scons. Copyrighted by the SCONS
Foundation. Released under an MIT license.
- C-Ares, an asynchronous DNS client, located at deps/c-ares. Copyright by
the Massachusetts Institute of Technology; authored by Greg Hudson,
Daniel Stenberg and others. Released under an MIT license.
- Node, optionally, dynmaically links to OpenSSL, cryptographic software
written by Eric Young (eay@cryptsoft.com) to provide SSL/TLS encryption.
OpenSSL is copyrighted by The OpenSSL Project. OpenSSL has a simple
Apache-style license. OpenSSL is not included in the Node distribution.
See http://openssl.org/ for more information.
- tools/doctool/markdown.js is Released under MIT license and
Copyright 2009-2010 Dominic Baggott and Ash Berli
- HTTP Parser, located at deps/http_parser, is a small C library
copyrighted by Ryan Lienhart Dahl and has a MIT license.
- src/platform_darwin_proctitle.cc, has code taken from the Chromium
project copyright Google Inc. and released with the BSD license.
- tools/closure_linter is copyrighted by The Closure Linter Authors and
Google Inc and is released under the Apache license.
- tools/cpplint.py is copyrighted by Google Inc and is released under the
BSD license.
Node's license follows:
Copyright 2009, 2010 Ryan Lienhart Dahl. All rights reserved.
====
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
......@@ -60,4 +19,50 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
IN THE SOFTWARE.
====
This license applies to all parts of Node that are not externally
maintained libraries.
The externally maintained libraries used by Node are:
- v8, located at deps/v8. v8 is copyright Google, Inc, and released
under a BSD license.
- libev, located at deps/libev, and libeio, located at deps/libeio. libev
and libeio are copyright Marc Alexander Lehmann, and dual-licensed
under the MIT license and GPL2.
- WAF build system, located at tools/waf. WAF is copyright Thomas Nagy,
and released under the MIT license.
- The SCONS build system, located at tools/scons. SCONS is copyright
the SCONS Foundation and released under the MIT license.
- C-Ares, an asynchronous DNS client, located at deps/c-ares. C-Ares is
copyright the Massachusetts Institute of Technology, authored by
Greg Hudson, Daniel Stenberg and others, and released under the MIT
license.
- Node, optionally, dynamically links to OpenSSL, cryptographic software
written by Eric Young (eay@cryptsoft.com) to provide SSL/TLS encryption.
OpenSSL is copyright The OpenSSL Project and released under the OpenSSL
license. OpenSSL is not included in the Node distribution.
See http://openssl.org/ for more information.
- tools/doctool/markdown.js is copyright 2009-2010 Dominic Baggott and Ash
Berli and released under the MIT license.
- HTTP Parser, located at deps/http_parser, is a small C library
copyright Ryan Lienhart Dahl and released under the MIT license.
- src/platform_darwin_proctitle.cc, has code taken from the Chromium
project copyright Google Inc. and released under a BSD license.
- tools/closure_linter is copyright The Closure Linter Authors and
Google Inc. and released under the Apache License, version 2.0.
- tools/cpplint.py is copyright Google Inc. and released under a
BSD license.
......@@ -61,6 +61,8 @@ endif()
if(${node_platform} MATCHES darwin)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Carbon")
# explicitly set this so that we don't check again when building libeio
set(HAVE_FDATASYNC 0)
else()
# OSX fdatasync() check wrong: http://public.kitware.com/Bug/view.php?id=10044
check_function_exists(fdatasync HAVE_FDATASYNC)
......
......@@ -62,6 +62,7 @@ set(node_sources
src/node_script.cc
src/node_os.cc
src/node_dtrace.cc
src/node_string.cc
src/node_natives.h
${node_extra_src})
......
......@@ -694,7 +694,7 @@ def GuessStrictAliasing(env):
env = Environment(tools=['gcc'])
version = subprocess.Popen([env['CC'], '-dumpversion'],
stdout=subprocess.PIPE).communicate()[0]
if version.find('4.5.') == 0:
if version.find('4.5') == 0:
return 'off'
return 'default'
......
......@@ -1153,7 +1153,7 @@ void DeferredInlineSmiOperation::GenerateNonSmiInput() {
}
// Check that the *signed* result fits in a smi. Not necessary for AND, SAR
// if the shift if more than 0 or SHR if the shit is more than 1.
if (!( (op_ == Token::AND) ||
if (!( (op_ == Token::AND && value_ >= 0) ||
((op_ == Token::SAR) && (shift_value > 0)) ||
((op_ == Token::SHR) && (shift_value > 1)))) {
__ add(r3, int32, Operand(0x40000000), SetCC);
......@@ -1414,8 +1414,10 @@ void CodeGenerator::SmiOperation(Token::Value op,
default: UNREACHABLE();
}
deferred->BindExit();
TypeInfo result_type =
(op == Token::BIT_AND) ? TypeInfo::Smi() : TypeInfo::Integer32();
TypeInfo result_type = TypeInfo::Integer32();
if (op == Token::BIT_AND && int_value >= 0) {
result_type = TypeInfo::Smi();
}
frame_->EmitPush(tos, result_type);
}
break;
......
......@@ -115,7 +115,7 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
patcher.masm()->mov(v8::internal::lr, v8::internal::pc);
patcher.masm()->ldr(v8::internal::pc, MemOperand(v8::internal::pc, -4));
#endif
patcher.Emit(Debug::debug_break_return()->entry());
patcher.Emit(Debug::debug_break_slot()->entry());
}
......
......@@ -703,38 +703,40 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
return result;
}
FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
HistogramTimerScope timer(&Counters::parse_lazy);
Handle<String> source(String::cast(script_->source()));
Counters::total_parse_size.Increment(source->length());
Handle<SharedFunctionInfo> shared_info = info->shared_info();
// Initialize parser state.
source->TryFlatten();
if (source->IsExternalTwoByteString()) {
ExternalTwoByteStringUC16CharacterStream stream(
Handle<ExternalTwoByteString>::cast(source),
info->start_position(),
info->end_position());
shared_info->start_position(),
shared_info->end_position());
FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
return result;
} else {
GenericStringUC16CharacterStream stream(source,
info->start_position(),
info->end_position());
shared_info->start_position(),
shared_info->end_position());
FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
return result;
}
}
FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
UC16CharacterStream* source,
ZoneScope* zone_scope) {
Handle<SharedFunctionInfo> shared_info = info->shared_info();
scanner_.Initialize(source);
ASSERT(target_stack_ == NULL);
Handle<String> name(String::cast(info->name()));
Handle<String> name(String::cast(shared_info->name()));
fni_ = new FuncNameInferrer();
fni_->PushEnclosingName(name);
......@@ -746,18 +748,20 @@ FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
{
// Parse the function literal.
Handle<String> no_name = Factory::empty_symbol();
Scope* scope =
NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
if (!info->closure().is_null()) {
scope = Scope::DeserializeScopeChain(info, scope);
}
LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
scope);
TemporaryScope temp_scope(&this->temp_scope_);
if (info->strict_mode()) {
if (shared_info->strict_mode()) {
temp_scope.EnableStrictMode();
}
FunctionLiteralType type =
info->is_expression() ? EXPRESSION : DECLARATION;
shared_info->is_expression() ? EXPRESSION : DECLARATION;
bool ok = true;
result = ParseFunctionLiteral(name,
false, // Strict mode name already checked.
......@@ -775,7 +779,7 @@ FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
zone_scope->DeleteOnExit();
if (stack_overflow_) Top::StackOverflow();
} else {
Handle<String> inferred_name(info->inferred_name());
Handle<String> inferred_name(shared_info->inferred_name());
result->set_inferred_name(inferred_name);
}
return result;
......@@ -5133,7 +5137,7 @@ bool ParserApi::Parse(CompilationInfo* info) {
Handle<Script> script = info->script();
if (info->is_lazy()) {
Parser parser(script, true, NULL, NULL);
result = parser.ParseLazy(info->shared_info());
result = parser.ParseLazy(info);
} else {
bool allow_natives_syntax =
FLAG_allow_natives_syntax || Bootstrapper::IsActive();
......
......@@ -426,7 +426,7 @@ class Parser {
bool in_global_context,
StrictModeFlag strict_mode);
FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info);
FunctionLiteral* ParseLazy(CompilationInfo* info);
void ReportMessageAt(Scanner::Location loc,
const char* message,
......@@ -441,7 +441,7 @@ class Parser {
// construct a hashable id, so if more than 2^17 are allowed, this
// should be checked.
static const int kMaxNumFunctionParameters = 32766;
FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info,
FunctionLiteral* ParseLazy(CompilationInfo* info,
UC16CharacterStream* source,
ZoneScope* zone_scope);
enum Mode {
......
......@@ -45,7 +45,7 @@
#include <errno.h>
#include <ieeefp.h> // finite()
#include <signal.h> // sigemptyset(), etc
#include <sys/kdi_regs.h>
#include <sys/regset.h>
#undef MAP_TYPE
......@@ -612,11 +612,16 @@ static Sampler* active_sampler_ = NULL;
static pthread_t vm_tid_ = 0;
static pthread_t GetThreadID() {
return pthread_self();
}
static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
USE(info);
if (signal != SIGPROF) return;
if (active_sampler_ == NULL || !active_sampler_->IsActive()) return;
if (vm_tid_ != pthread_self()) return;
if (vm_tid_ != GetThreadID()) return;
TickSample sample_obj;
TickSample* sample = CpuProfiler::TickSampleEvent();
......@@ -627,17 +632,10 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
mcontext_t& mcontext = ucontext->uc_mcontext;
sample->state = Top::current_vm_state();
#if V8_HOST_ARCH_IA32
sample->pc = reinterpret_cast<Address>(mcontext.gregs[KDIREG_EIP]);
sample->sp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_ESP]);
sample->fp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_EBP]);
#elif V8_HOST_ARCH_X64
sample->pc = reinterpret_cast<Address>(mcontext.gregs[KDIREG_RIP]);
sample->sp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_RSP]);
sample->fp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_RBP]);
#else
UNIMPLEMENTED();
#endif
sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]);
sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
active_sampler_->SampleStack(sample);
active_sampler_->Tick(sample);
}
......@@ -645,26 +643,86 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
class Sampler::PlatformData : public Malloced {
public:
PlatformData() {
signal_handler_installed_ = false;
enum SleepInterval {
FULL_INTERVAL,
HALF_INTERVAL
};
explicit PlatformData(Sampler* sampler)
: sampler_(sampler),
signal_handler_installed_(false),
vm_tgid_(getpid()),
signal_sender_launched_(false) {
}
void SignalSender() {
while (sampler_->IsActive()) {
if (rate_limiter_.SuspendIfNecessary()) continue;
if (sampler_->IsProfiling() && RuntimeProfiler::IsEnabled()) {
SendProfilingSignal();
Sleep(HALF_INTERVAL);
RuntimeProfiler::NotifyTick();
Sleep(HALF_INTERVAL);
} else {
if (sampler_->IsProfiling()) SendProfilingSignal();
if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
Sleep(FULL_INTERVAL);
}
}
}
void SendProfilingSignal() {
if (!signal_handler_installed_) return;
pthread_kill(vm_tid_, SIGPROF);
}
void Sleep(SleepInterval full_or_half) {
// Convert ms to us and subtract 100 us to compensate delays
// occuring during signal delivery.
useconds_t interval = sampler_->interval_ * 1000 - 100;
if (full_or_half == HALF_INTERVAL) interval /= 2;
int result = usleep(interval);
#ifdef DEBUG
if (result != 0 && errno != EINTR) {
fprintf(stderr,
"SignalSender usleep error; interval = %u, errno = %d\n",
interval,
errno);
ASSERT(result == 0 || errno == EINTR);
}
#endif
USE(result);
}
Sampler* sampler_;
bool signal_handler_installed_;
struct sigaction old_signal_handler_;
struct itimerval old_timer_value_;
int vm_tgid_;
bool signal_sender_launched_;
pthread_t signal_sender_thread_;
RuntimeProfilerRateLimiter rate_limiter_;
};
static void* SenderEntry(void* arg) {
Sampler::PlatformData* data =
reinterpret_cast<Sampler::PlatformData*>(arg);
data->SignalSender();
return 0;
}
Sampler::Sampler(int interval)
: interval_(interval),
profiling_(false),
active_(false),
samples_taken_(0) {
data_ = new PlatformData();
data_ = new PlatformData(this);
}
Sampler::~Sampler() {
ASSERT(!data_->signal_sender_launched_);
delete data_;
}
......@@ -672,43 +730,53 @@ Sampler::~Sampler() {
void Sampler::Start() {
// There can only be one active sampler at the time on POSIX
// platforms.
if (active_sampler_ != NULL) return;
ASSERT(!IsActive());
vm_tid_ = GetThreadID();
// Request profiling signals.
struct sigaction sa;
sa.sa_sigaction = ProfilerSignalHandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return;
data_->signal_handler_installed_ = true;
// Set the itimer to generate a tick for each interval.
itimerval itimer;
itimer.it_interval.tv_sec = interval_ / 1000;
itimer.it_interval.tv_usec = (interval_ % 1000) * 1000;
itimer.it_value.tv_sec = itimer.it_interval.tv_sec;
itimer.it_value.tv_usec = itimer.it_interval.tv_usec;
setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_);
sa.sa_flags = SA_RESTART | SA_SIGINFO;
data_->signal_handler_installed_ =
sigaction(SIGPROF, &sa, &data_->old_signal_handler_) == 0;
// Start a thread that sends SIGPROF signal to VM thread.
// Sending the signal ourselves instead of relying on itimer provides
// much better accuracy.
SetActive(true);
if (pthread_create(
&data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
data_->signal_sender_launched_ = true;
}
// Set this sampler as the active sampler.
active_sampler_ = this;
active_ = true;
}
void Sampler::Stop() {
SetActive(false);
// Wait for signal sender termination (it will exit after setting
// active_ to false).
if (data_->signal_sender_launched_) {
Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
pthread_join(data_->signal_sender_thread_, NULL);
data_->signal_sender_launched_ = false;
}
// Restore old signal handler
if (data_->signal_handler_installed_) {
setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL);
sigaction(SIGPROF, &data_->old_signal_handler_, 0);
data_->signal_handler_installed_ = false;
}
// This sampler is no longer the active sampler.
active_sampler_ = NULL;
active_ = false;
}
#endif // ENABLE_LOGGING_AND_PROFILING
} } // namespace v8::internal
......@@ -148,13 +148,14 @@ Scope::Scope(Scope* inner_scope, SerializedScopeInfo* scope_info)
unresolved_(16),
decls_(4) {
ASSERT(scope_info != NULL);
SetDefaults(FUNCTION_SCOPE, inner_scope->outer_scope(), scope_info);
SetDefaults(FUNCTION_SCOPE, NULL, scope_info);
ASSERT(resolved());
InsertAfterScope(inner_scope);
if (scope_info->HasHeapAllocatedLocals()) {
num_heap_slots_ = scope_info_->NumberOfContextSlots();
}
AddInnerScope(inner_scope);
// This scope's arguments shadow (if present) is context-allocated if an inner